Search code examples
javaindexoflastindexof

Printing last index of string in a string without using lastIndexOf method


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

Solution

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