Home > Enterprise >  Count all 4-letter Substring within the given String that matches ignore case a particular String
Count all 4-letter Substring within the given String that matches ignore case a particular String

Time:11-14

I need to create a program in Java that finds all the occurrences of a 4-letter string, in this case "lane", within the given String.

Comparison should be case-insensitive, and the second letter of the matching substring should not be taken into account while evaluating whether a substring matches or not.

My current code can handle some cases, but in others it returns an incorrect number of occurrences or produces an IndexOutOfBoundsException.

I tried the following cases:

  1. "Lanee" - returns 1, as expected ("Lane" matches "lane").
  2. "LineLone" - returns 2, as expected (both "Line" and "Lone"match"lane"`).
  3. "LLoenLL" - produces an IndexOutOfBoundsException.
  4. "enaLLLmnee" - returns 0, but should be 1
  5. "LLONElllneL" - produces an IndexOutOfBoundsException.

My code:

public class Stringer {

    public Stringer() {}
    
    public int getOccurrences(String s) {

        String lower = s.toLowerCase();
        int occurrences = 0;
        int x = 0;

        while (x < lower.length()) {
            int traverser = lower.indexOf("l", x);
            if (traverser != -1 && lower.length() > 3) {
                String sub = lower.substring(x  = 2, x  = 2);

                if (sub.equals("ne")) {
                    occurrences  ;
                }
            } else {
                break;
            }
        }
        return occurrences;
    }
}

How can I resolve this issue?

CodePudding user response:

Basically, you need to iterate over the given string, checking if the current character is equal to 'l' (the first character of "lane").

And if the that's the case, you need to check the if character at the current index 2 and 3 match 'n' and 'e' respectively. If all these characters match, the number of occurrences should be incremented and the index advanced by 3 to avoid double-checking the same positions.

Note that termination condition in the loop is i < lower.length() - 3 because the length of the target string "lane" is 4 and while checking the first character of a substring at index i we need to be able to the last substring character at index i 3.

public static int getOccurrences(String s) {
    String lower = s.toLowerCase();
    int occurrences = 0;
    
    for (int i = 0; i < lower.length() - 3; i  ) {
        if (lower.charAt(i) == 'l' &&
            lower.charAt(i   2) == 'n' &&
            lower.charAt(i   3) == 'e') {

            occurrences  ; // incrementing the number of occurrences
            i  = 3;        // advancing the index
        }
    }
    return occurrences;
}

main()

public static void main(String[] args) {
    System.out.println(getOccurrences("Lanee"));
    System.out.println(getOccurrences("LineLone"));
    System.out.println(getOccurrences("LLoenLL"));
    System.out.println(getOccurrences("enaLLLmnee"));
    System.out.println(getOccurrences("LLONElllneL"));
}

Output:

1
2
0
1
2

CodePudding user response:

You can also make use of regular expressions to solve this.

public static void main(String[] args) {
    System.out.println(getOccurrences("Lanee"));
    System.out.println(getOccurrences("LineLone"));
    System.out.println(getOccurrences("LLoenLL"));
    System.out.println(getOccurrences("enaLLLmnee"));
    System.out.println(getOccurrences("LLONElllneL"));
}

prints

1
2
0
1
2

Regular expressions can be used to match patterns in strings

  • (?i) - uses the i flag which says ignore case when matching
  • l.ne - is the string to match. The . stands for any character
  • the Matcher takes the source string and iterates across the string trying to find matches. If it returns true, count is updated.
public static int getOccurrences(String s) {
   Matcher m = Pattern.compile("(?i)l.ne").matcher(s);
   int count = 0;
   while (m.find()) {
       count  ;
   }
   return count;
}

You could also use the following method signature to take any target string. Then you just need to build the expression using the target.

public static int getOccurrences(String s, String target) {
    String expression = "(?i)" target.substring(0,1) "." target.substring(2);
    Matcher m = Pattern.compile(expression).matcher(s);
    int count = 0;
    while (m.find()) {
        count  ;
    }
    return count;
}

Calling it like this, the output would be the same.

System.out.println(getOccurrences("Lanee", "lane"));
System.out.println(getOccurrences("LineLone", "LANE"));
System.out.println(getOccurrences("LLoenLL", "LaNe"));
System.out.println(getOccurrences("enaLLLmnee","lanE"));
System.out.println(getOccurrences("LLONElllneL", "Lane"));
  • Related