1

Note: This question is asked for a school assignment. I fell I'm getting close to the true code, there are only a few points left to be taken care of.

I am asked to write a method that receives two strings(s1 and s2) and checks whether s2 is in s1 case sensitively. If s2 is in s1 it returns the index of the last occurrence of s2, otherwise it returns -1.

So, here is my code:

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;
    }

But this method returns first index of s2 or it is just a copy of IndexOf method. Output for s1 = aabbccbbe and s2 = bb is 2.

EDIT : @eli's code

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;
    }
5
  • contains("Greetings", "error") will return 2 I think, even though "Greetings" doesn't contain "error" and it should therefore return -1. Commented Nov 22, 2016 at 20:02
  • @Gendarme contains("Greetings", "error") returned 1. Commented Nov 22, 2016 at 20:06
  • Yeah, you're right. Even more weird. It returns the index in s1 of the first letter that they both have, in this case r. Commented Nov 22, 2016 at 20:08
  • might be help : grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/… Commented Nov 22, 2016 at 20:19
  • Think of your strings as array of characters. Reverse both arrays and find first indexof Commented Nov 22, 2016 at 20:30

3 Answers 3

1

First of all, close any resource you open when you're done with it.

input.close();

If it is allowed you can just use regex:

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;
}

The regex pattern is explained here.

With find() you make sure that at least one occurrence is present. As the pattern can result in 1 and only 1 result, you can just ask for the "first index of first occurrence" in the matcher, achieved with start().

EDIT Okay, I can see you can't use anything but charAt and length. Here's a different solution without regex, substring, indexOf or what-so-ever:

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;
}

I must admit I didn't thoroughly test this.

FINAL I've done some minor fixes for you. I don't know how you were capable of compiling what you edited in your post. Here's a working sample:

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;
    }
}
Sign up to request clarification or add additional context in comments.

9 Comments

Thanks a lot but this is not what I'm looking for. This method returns -1for any s1 with spaces in it.
You're doing something very weird then.
Testing: String s1 = "The quick brown fox jumps over the lazy dog."; String s2 = "the"; Returns (as expected) 31.
Can you please make an edit in your original post with what you've edited code to (with my solution, that is)?
I have given a full sample code now. You were missing a bracer for you main method. Also, note how I close the resource at the end, this is what I meant in the first edition of my answer.
|
1

I think it will boil down to looping through string characters and storing the last index of occurred match. Here is not perfect, but simple example without use of 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;
}

Comments

1

Say you have the string called sentence: The quick brown fox jumps over the lazy dog. and you want to find the last occurrence of "the", called token.

sentence.length = 44 and token.length = 3

Consider this somewhat java pseudo code:

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;
}

EDIT

Here is the full application using only length and 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;
  }
}

EDIT 2

You also have a bug in the way you are reading your input. You need to use input.readLine() to get the full line. input.read breaks on spaces. Along those lines, you also need a new scanner for each line you want to read.

EDIT 3

Here is the whole source:

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;
  }
}

5 Comments

Sure, but I'm not allowed to use the built-in String methods except charAt and length.
Sure, but isn't this code return first index of s2? Cause it returns -1 for sentence : The quick brown fox jumps over the lazy dog . Thanks by the way.
Thank you so much but it returns -1 when you enter inputs by hand in int indexOf = lastIndexOf(sentence, token); System.out.print(indexOf); for sentence = The quick brown fox jumps over the lazy dog. How to get lastindexof?
Yes. Sentence comes first and then token.
Can't use readLine() method, it says "undefined for type Scanner".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.