Печать последнего индекса строки в строке без использования метода lastIndexOf

Примечание. Этот вопрос задается для школьного задания. Я упал, приближаясь к истинному коду, осталось лишь несколько моментов, о которых нужно позаботиться.

Меня просят написать метод, который получает две строки (s1 и s2) и проверяет, чувствителен ли s2 в случае s1. Если s2 находится в s1, он возвращает индекс последнего вхождения s2, в противном случае он возвращает -1.

Итак, вот мой код:

import java.util.*;
public class homework4 {


    public static void main(String args[]) {
        Scanner input = new Scanner(System.in);
        System.out.println("\nEnter a choice: ");
        int choice = input.nextInt();
        if(choice == 1) {
            System.out.println("Enter firts string: ");
                String s1 = input.next();
            System.out.println("Enter second string: ");
                String s2 = input.next();
            System.out.print(contains(s1,s2));
            }
            else {
                //Call other methods...
           }
    public static int contains (String s1, String s2) {
        for(int i = 0; i<s1.length(); i++) {
            for(int j = 0; j<s2.length(); j++) {
                char ch = s2.charAt(j);
                if(s1.charAt(i) == ch) {
                    return i;
                }
            }   
        }   
        return -1;
    }

Но этот метод возвращает первый индекс s2 или это просто копия метода IndexOf. Выход для s1 = aabbccbbe а также s2 = bb является 2,

РЕДАКТИРОВАТЬ: @ Эли код

import java.util.*;
    public class homework4 {


        public static void main(String args[]) {
            Scanner input = new Scanner(System.in);
            System.out.println("\nEnter a choice: ");
            int choice = input.nextInt();
            if(choice == 1) {
                System.out.println("Enter firts string: ");
                    String s1 = input.next();
                System.out.println("Enter second string: ");
                    String s2 = input.next();
                System.out.print(contains(s1,s2));
                }
                else {
                    //Call other methods...
               }
       public static int contains(String s1, String s2) {
        int i = s2.length()-1, j = s1.length()-1;

        if(i > j)
            return -1;

        for(; i > -1; i--) {
            for(; j >= 0; j--) {
                if(s1.charAt(j) == s2.charAt(i)) {
                    if(i == 0)
                        return j;

                    if(j != 0)
                        j--;

                    break;
                } else if(i != s2.length()) {
                    i = s2.length()-1;
                }
            }
        }

        return -1;
    }

3 ответа

Решение

Прежде всего закройте любой ресурс, который вы открываете, когда закончите с ним.

input.close();

Если это разрешено, вы можете просто использовать регулярные выражения:

public static int contains (String s1, String s2) {
    Pattern p = Pattern.compile(s2+"(?!.*"+s2+")");
    Matcher m = p.matcher(s1);

    if(m.find())
        return m.start();

    return -1;
}

Шаблон регулярных выражений объясняется здесь.

С find() Вы убедитесь, что присутствует хотя бы одно вхождение. Поскольку шаблон может привести к 1 и только 1 результату, вы можете просто запросить "первый индекс первого вхождения" в сопоставителе, достигнутый с помощью start(),

РЕДАКТИРОВАТЬ Хорошо, я вижу, что вы не можете использовать ничего, кроме charAt а также length, Вот другое решение без регулярного выражения, подстроки, indexOf или чего-то еще:

public static int contains(String s1, String s2) {
    int i = s2.length()-1, j = s1.length()-1;

    if(i > j)
        return -1;

    for(; i > -1; i--) {
        for(; j >= 0; j--) {
            if(s1.charAt(j) == s2.charAt(i)) {
                if(i == 0)
                    return j;

                if(j != 0)
                    j--;

                break;
            } else if(i != s2.length()) {
                i = s2.length()-1;
            }
        }
    }

    return -1;
}

Я должен признать, что я не проверил это полностью.

ЗАКЛЮЧИТЕЛЬНО Я сделал несколько небольших исправлений для вас. Я не знаю, как вы смогли собрать то, что вы отредактировали в своем посте. Вот рабочий образец:

import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class homework4 {
    public static void main(String args[]) {
        Scanner input = new Scanner(System.in);

        System.out.println("Enter choice: ");

        switch (input.nextInt()) {
        // If 1 is given as input...
        case 1:
            // As we press "enter" after inputting 1, the newline is read by the
            // scanner. We skip this newline by doing this.
            input.nextLine();

            System.out.println("Enter first string: ");
            String s1 = input.nextLine();

            System.out.println("Enter second string: ");
            String s2 = input.nextLine();

            System.out.println("Result: " + contains(s1, s2));
            break;
        // If 2 is given as input (just for the sake of the example)
        case 2:
            System.out.println("You chose an unimplemented choice.");
            break;
        // If something else is given as input...
        default:
            System.out.println("Nothing to do...");
            break;
        }

        // As Scanner is considered a resource, we have to close it, now that
        // we're done using it.
        input.close();
    }

    // This is the RegEx implementation
    public static int containsRegx(String s1, String s2) {
        Pattern p = Pattern.compile(s2 + "(?!.*" + s2 + ")");
        Matcher m = p.matcher(s1);

        if (m.find())
            return m.start();

        return -1;
    }

    // This is the charAt and length only
    public static int contains(String s1, String s2) {
        int i = s2.length() - 1, j = s1.length() - 1;

        if(i > j || i * j == 0)
            return -1;

        for (; i > -1; i--) {
            for (; j >= 0; j--) {
                if (s1.charAt(j) == s2.charAt(i)) {
                    if (i == 0)
                        return j;

                    if (j != 0)
                        j--;

                    break;
                } else if (i != s2.length()) {
                    i = s2.length() - 1;
                }
            }
        }

        return -1;
    }
}

Я думаю, что все сводится к циклическому прохождению строковых символов и сохранению последнего индекса произошедшего совпадения. Вот не идеальный, но простой пример без использования indexOf:

public static int contains(String s1, String s2) {
    if(s1.length() < s2.length())
        return -1;

    int lastOccurrence = -1;
    for (int i = 0; i < s1.length(); ) {
        if (s1.startsWith(s2, i)) {
            lastOccurrence = i + s2.length() - 1;
            i = lastOccurrence + 1;
        }
        else {
            ++i;
        }
    }
    return lastOccurrence;
}

Скажем, у вас есть строка под названием sentenceБыстрая коричневая лиса перепрыгивает через ленивую собаку. и вы хотите найти последнее вхождение "the", называемое token,

sentence.length = 44 а также token.length = 3

Рассмотрим этот несколько псевдо-код Java:

public static int lastIndexOf(String sentence, String token) {
    //The starting index is the first possible location your token could fit
    int startingIndex = sentence.length() - token.length();
    //move backwards one character at a time until you reach 0
    //checking for string fragment that equals your token at each iteration
    for (int i = startingIndex; i >= 0; i--) {
         String fragment = sentence.substring(i, i + token.length());
         if (fragment.equals(token)) return i;
    }
    return -1;
}

РЕДАКТИРОВАТЬ

Вот полное приложение, использующее только length и charAt():

public class HelloWorld
{
  // arguments are passed using the text field below this editor
  public static void main(String[] args)
  {
    int indexOf = lastIndexOf("The quick brown fox jumps over the lazy dog.", "the");
    System.out.print(indexOf);
  }

  public static int lastIndexOf(String sentence, String token) {
    int startingIndex = sentence.length() - token.length();
    for (int i = startingIndex; i >= 0; i--) {
        String fragment = substring(sentence, i, i + token.length());
        if (strEquals(token, fragment)) return i;
    }
    return -1;
  }

  public static String substring(String str, int startingIndex, int endingIndex) {
    int size = endingIndex - startingIndex;
    char[] arr = new char[size];

    for (int i = 0; i < size; i++) {
      arr[i] = str.charAt(startingIndex+i);
    }
    return new String(arr);
  }

  public static boolean strEquals(String s1, String s2) {
    if (s1.length() != s2.length()) return false;

    for (int i = 0; i < s1.length(); i++) {
      if (s1.charAt(i) == s2.charAt(i)) continue;
      return false;
    }

    return true;
  }
}

РЕДАКТИРОВАТЬ 2

У вас также есть ошибка в том, как вы читаете свой ввод. Вам нужно использовать input.readLine() чтобы получить полную линию. input.read перерывы на пространствах. Вдоль этих строк вам также понадобится новый сканер для каждой строки, которую вы хотите прочитать.

РЕДАКТИРОВАТЬ 3

Вот весь источник:

import java.util.Scanner;

public class HelloWorld {
  public static void main(String[] args)
  {
      Scanner input1 = new Scanner(System.in);
      System.out.println("\nEnter a choice: ");
      String s1="";
      String s2="";
      int choice = input1.nextInt();
      if(choice == 1) {
          Scanner input2 = new Scanner(System.in);
          System.out.println("Enter first string: ");
          s1 = input2.nextLine();
          Scanner input3 = new Scanner(System.in);
          System.out.println("Enter second string: ");
          s2 = input3.nextLine();
        }

    int indexOf = lastIndexOf(s1, s2);
    System.out.println(indexOf);
  }

  public static int lastIndexOf(String sentence, String token) {
    int startingIndex = sentence.length() - token.length();
    for (int i = startingIndex; i >= 0; i--) {
        String fragment = substring(sentence, i, i + token.length());
        if (strEquals(token, fragment)) return i;
    }
    return -1;
  }

  public static String substring(String str, int startingIndex, int endingIndex) {
    int size = endingIndex - startingIndex;
    char[] arr = new char[size];

    for (int i = 0; i < size; i++) {
      arr[i] = str.charAt(startingIndex+i);
    }
    return new String(arr);
  }

  public static boolean strEquals(String s1, String s2) {
    if (s1.length() != s2.length()) return false;

    for (int i = 0; i < s1.length(); i++) {
      if (s1.charAt(i) == s2.charAt(i)) continue;
      return false;
    }

    return true;
  }
}
Другие вопросы по тегам