Count Occurrences of Substring in Java
Problem
Counting occurrences means finding how many times a substring appears in a larger string, moving past each match found so the same characters aren't counted twice.
Given a string and a target substring, count how many times the substring occurs.
Java Program
public class CountSubstringOccurrences {
public static void main(String[] args) {
String str = "the cat sat on the mat";
String sub = "at";
int count = 0;
int index = 0;
while ((index = str.indexOf(sub, index)) != -1) { // searches for the next match starting from the current index
count++;
index += sub.length(); // move past this match to avoid re-counting overlaps
}
System.out.println("Occurrences: " + count);
}
}Output
Core Logic
Repeatedly searching from just past the last match, using indexOf() with a starting offset, finds every occurrence in a single left-to-right sweep.
- 1
str.indexOf(sub, index)searches for the next occurrence ofsub, starting from positionindex. - 2As long as a match is found (the result isn't
-1),countis incremented. - 3
indexis advanced bysub.length()after each match, moving the search past the characters just matched. - 4The loop stops once
indexOf()returns-1, meaning no further occurrences exist.
"the cat sat on the mat", "at" is found inside 'cat', 'sat', and 'mat' — three non-overlapping matches.Key Point: Advancing by sub.length() rather than by 1 is what makes this count non-overlapping occurrences — advancing by 1 instead would also catch overlapping matches, like counting "aa" twice in "aaa".
Why: Each call to indexOf() may need to compare up to m characters at every position it tries, and the search restarts just past each match found.
Key Concepts
Approach 2: Replace Trick
public class CountSubstringOccurrencesTrick {
public static void main(String[] args) {
String str = "the cat sat on the mat";
String sub = "at";
// Removing every occurrence shrinks the string by (occurrences * sub.length())
int count = (str.length() - str.replace(sub, "").length()) / sub.length();
System.out.println("Occurrences: " + count);
}
}
Output
Core Logic
Removing every occurrence of the substring shrinks the string by exactly (occurrences × substring length) — so the occurrence count can be worked backward from that shrinkage.
- 1
str.replace(sub, "")deletes every occurrence ofsub, producing a shorter string. - 2
str.length() - replaced.length()gives the total number of characters removed. - 3Dividing that difference by
sub.length()gives back the number of timessubwas removed — the occurrence count.
"at" from "the cat sat on the mat" (23 characters) leaves "the c s on the m" (17 characters) — a difference of 6, divided by 2 gives 3 occurrences.Key Point: This is a neat one-liner, but it does the same underlying scan as indexOf() internally — the appeal here is brevity, not a different algorithm.
Why: replace() has to scan the whole string and build an entirely new string with the matches removed, before the length arithmetic can run.