Given two strings s1 and s2, consisting of lowercase English letters, find the number of occurrences of s2 as a substring in s1. Overlapping occurrences should also be counted.
Examples:
Input: s1 = "gfggfg", s2 = "gfg"
Output: 2
Explanation: s2 occurs twice in s1. Once starting at index 0 and once starting at index 3 .Input: s1 = "banana", s2 = "nn"
Output: 0
Explanation: s2 does not occur in s1.Input: s1 = "aaaaa", s2 = "aa"
Output: 4
Explanation: s2 occurs at indices 0, 1, 2, and 3 in s1. Overlapping occurrences are also counted.
Table of Content
[Naive Approach] Nested Loop Substring Comparison - O(|s1|*|s2|) Time and O(1) Space
Check every starting index in s1 as a possible match for s2, comparing characters one by one. The starting index always moves forward by just one position, whether or not a match was found, so overlapping occurrences are counted correctly.
Step by Step Implementation:
- Let n be the length of s1 and m be the length of s2.
- Iterate the starting index i from 0 to n - m (inclusive), since s2 cannot fit starting any later than that.
- At each i, compare s1[i], s1[i+1], ..., s1[i+m-1] against s2[0], s2[1], ..., s2[m-1] character by character.
- If every character matches, increment the count.
- Move to the next starting index and repeat, so overlapping matches are also counted.
- Return the final count.
#include <iostream>
#include <string>
using namespace std;
// function to count occurrences of s2 in s1 using nested loop comparison
int countFreq(string s1, string s2) {
int n = s1.size();
int m = s2.size();
int count = 0;
// try every possible starting index in s1
for (int i = 0; i <= n - m; i++) {
int j = 0;
// compare characters of s2 with s1 starting at index i
while (j < m && s1[i + j] == s2[j]) {
j++;
}
// if all characters matched, count this occurrence
if (j == m) {
count++;
}
}
return count;
}
int main() {
string s1 = "gfggfg";
string s2 = "gfg";
cout << countFreq(s1, s2) << endl;
return 0;
}
class GFG {
// function to count occurrences of s2 in s1 using nested loop comparison
static int countFreq(String s1, String s2) {
int n = s1.length();
int m = s2.length();
int count = 0;
// try every possible starting index in s1
for (int i = 0; i <= n - m; i++) {
int j = 0;
// compare characters of s2 with s1 starting at index i
while (j < m && s1.charAt(i + j) == s2.charAt(j)) {
j++;
}
// if all characters matched, count this occurrence
if (j == m) {
count++;
}
}
return count;
}
public static void main(String[] args) {
String s1 = "gfggfg";
String s2 = "gfg";
System.out.println(countFreq(s1, s2));
}
}
# function to count occurrences of s2 in s1 using nested loop comparison
def countFreq(s1, s2):
n = len(s1)
m = len(s2)
count = 0
# try every possible starting index in s1
for i in range(n - m + 1):
j = 0
# compare characters of s2 with s1 starting at index i
while j < m and s1[i + j] == s2[j]:
j += 1
# if all characters matched, count this occurrence
if j == m:
count += 1
return count
if __name__ == "__main__":
s1 = "gfggfg"
s2 = "gfg"
print(countFreq(s1, s2))
using System;
class GFG {
// function to count occurrences of s2 in s1 using nested loop comparison
static int countFreq(string s1, string s2) {
int n = s1.Length;
int m = s2.Length;
int count = 0;
// try every possible starting index in s1
for (int i = 0; i <= n - m; i++) {
int j = 0;
// compare characters of s2 with s1 starting at index i
while (j < m && s1[i + j] == s2[j]) {
j++;
}
// if all characters matched, count this occurrence
if (j == m) {
count++;
}
}
return count;
}
static void Main(string[] args) {
string s1 = "gfggfg";
string s2 = "gfg";
Console.WriteLine(countFreq(s1, s2));
}
}
// function to count occurrences of s2 in s1 using nested loop comparison
function countFreq(s1, s2) {
let n = s1.length;
let m = s2.length;
let count = 0;
// try every possible starting index in s1
for (let i = 0; i <= n - m; i++) {
let j = 0;
// compare characters of s2 with s1 starting at index i
while (j < m && s1[i + j] === s2[j]) {
j++;
}
// if all characters matched, count this occurrence
if (j === m) {
count++;
}
}
return count;
}
// Driver Code
let s1 = "gfggfg";
let s2 = "gfg";
console.log(countFreq(s1, s2));
Output
2
[Expected Approach] Using KMP Algorithm - O(|s1| + |s2|) Time and O(|s2|) Space
Preprocess s2 into an LPS array using the KMP algorithm, storing for every prefix of s2 the length of its longest proper prefix that is also a suffix. This lets a mismatch fall back to a partially matched state instead of restarting from scratch, and on a full match, falling back the same way (instead of resetting to 0) lets overlapping occurrences be counted too.
Step by Step Implementation:
- Build the LPS array for s2: for each index, extend the match length if characters agree, or fall back using the LPS array itself if they don't.
- Scan s1 with a pointer j tracking how much of s2 has matched so far.
- On a mismatch, fall back j using the LPS array instead of restarting from index 0.
- On a match, advance j. If j reaches |s2|, count the occurrence and fall back j using the LPS array to continue checking for overlaps.
- Return the count once s1 is fully scanned.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
// function to count occurrences of s2 in s1 using kmp algorithm
int countFreq(string s1, string s2) {
int m = s2.size();
// build the lps array for s2
vector<int> lps(m, 0);
int length = 0;
for (int i = 1; i < m; i++) {
while (length > 0 && s2[i] != s2[length]) {
length = lps[length - 1];
}
if (s2[i] == s2[length]) {
length++;
}
lps[i] = length;
}
// use the lps array to count all overlapping occurrences of s2 in s1
int n = s1.size();
int count = 0;
int j = 0;
for (int i = 0; i < n; i++) {
while (j > 0 && s1[i] != s2[j]) {
j = lps[j - 1];
}
if (s1[i] == s2[j]) {
j++;
}
if (j == m) {
// full match found, count it and continue searching for overlaps
count++;
j = lps[j - 1];
}
}
return count;
}
int main() {
string s1 = "gfggfg";
string s2 = "gfg";
cout << countFreq(s1, s2) << endl;
return 0;
}
class GFG {
// function to count occurrences of s2 in s1 using kmp algorithm
static int countFreq(String s1, String s2) {
int m = s2.length();
// build the lps array for s2
int[] lps = new int[m];
int length = 0;
for (int i = 1; i < m; i++) {
while (length > 0 && s2.charAt(i) != s2.charAt(length)) {
length = lps[length - 1];
}
if (s2.charAt(i) == s2.charAt(length)) {
length++;
}
lps[i] = length;
}
// use the lps array to count all overlapping occurrences of s2 in s1
int n = s1.length();
int count = 0;
int j = 0;
for (int i = 0; i < n; i++) {
while (j > 0 && s1.charAt(i) != s2.charAt(j)) {
j = lps[j - 1];
}
if (s1.charAt(i) == s2.charAt(j)) {
j++;
}
if (j == m) {
// full match found, count it and continue searching for overlaps
count++;
j = lps[j - 1];
}
}
return count;
}
public static void main(String[] args) {
String s1 = "gfggfg";
String s2 = "gfg";
System.out.println(countFreq(s1, s2));
}
}
# function to count occurrences of s2 in s1 using kmp algorithm
def countFreq(s1, s2):
m = len(s2)
# build the lps array for s2
lps = [0] * m
length = 0
for i in range(1, m):
while length > 0 and s2[i] != s2[length]:
length = lps[length - 1]
if s2[i] == s2[length]:
length += 1
lps[i] = length
# use the lps array to count all overlapping occurrences of s2 in s1
n = len(s1)
count = 0
j = 0
for i in range(n):
while j > 0 and s1[i] != s2[j]:
j = lps[j - 1]
if s1[i] == s2[j]:
j += 1
if j == m:
# full match found, count it and continue searching for overlaps
count += 1
j = lps[j - 1]
return count
if __name__ == "__main__":
s1 = "gfggfg"
s2 = "gfg"
print(countFreq(s1, s2))
using System;
class GFG {
// function to count occurrences of s2 in s1 using kmp algorithm
static int countFreq(string s1, string s2) {
int m = s2.Length;
// build the lps array for s2
int[] lps = new int[m];
int length = 0;
for (int i = 1; i < m; i++) {
while (length > 0 && s2[i] != s2[length]) {
length = lps[length - 1];
}
if (s2[i] == s2[length]) {
length++;
}
lps[i] = length;
}
// use the lps array to count all overlapping occurrences of s2 in s1
int n = s1.Length;
int count = 0;
int j = 0;
for (int i = 0; i < n; i++) {
while (j > 0 && s1[i] != s2[j]) {
j = lps[j - 1];
}
if (s1[i] == s2[j]) {
j++;
}
if (j == m) {
// full match found, count it and continue searching for overlaps
count++;
j = lps[j - 1];
}
}
return count;
}
static void Main(string[] args) {
string s1 = "gfggfg";
string s2 = "gfg";
Console.WriteLine(countFreq(s1, s2));
}
}
// function to count occurrences of s2 in s1 using kmp algorithm
function countFreq(s1, s2) {
let m = s2.length;
// build the lps array for s2
let lps = new Array(m).fill(0);
let length = 0;
for (let i = 1; i < m; i++) {
while (length > 0 && s2[i] !== s2[length]) {
length = lps[length - 1];
}
if (s2[i] === s2[length]) {
length++;
}
lps[i] = length;
}
// use the lps array to count all overlapping occurrences of s2 in s1
let n = s1.length;
let count = 0;
let j = 0;
for (let i = 0; i < n; i++) {
while (j > 0 && s1[i] !== s2[j]) {
j = lps[j - 1];
}
if (s1[i] === s2[j]) {
j++;
}
if (j === m) {
// full match found, count it and continue searching for overlaps
count++;
j = lps[j - 1];
}
}
return count;
}
// Driver Code
let s1 = "gfggfg";
let s2 = "gfg";
console.log(countFreq(s1, s2));
Output
2