Given a string S of size N, the task is to count the occurrences of all the prefixes of the given string S.
Examples:
Input: S = “AAAA”
Output:
A occurs 4 times
AA occurs 3 times.
AAA occurs 2 times.
AAAA occurs 1 times.
Explanation:
Below is the illustration of all the prefix:
Input: S = “ABACABA”
Output:
A occurs 4 times
AB occurs 2 times
ABA occurs 2 times
ABAC occurs 1 times
ABACA occurs 1 times
ABACAB occurs 1 times
ABACABA occurs 1 times
Naive Approach:
- Traverse over all the prefixes in set P. Let the x be the prefix.
- Do a sliding window approach of size |x|.
- Check if the current sliding window on S is equal to x. If yes then increase the count[x] by 1.
Time complexity: O(N3)
Auxiliary Space: O(N)
Efficient Approach:
Use the LPS array (also called prefix_function) from the KMP algorithm.
The prefix function for this string is defined as an array LPS of length N, where LPS[i] is the length of the longest proper prefix of the substring S[0…i] which is also a suffix of this substring. Let occ[i] denote the number of occurrences of the prefix of length i.
Below are the steps to implement this approach:
- Compute the LPS array or prefix_function.
- For each value of the prefix function, first, count how many times it occurs in the LPS array.
- The length prefix i appears exactly ans[i] times, then this number must be added to the number of occurrences of its longest suffix that is also a prefix.
- In the end, add 1 to all the values of occ array, because of the original prefix that should be counted as well.
For example:
LPS[i] denotes that in position i, a prefix of length = LPS[i] appears. And this is the longest prefix possible. But shorter prefixes can occur.
For String S = “AAAA”, following are the prefixes:
S[0..0] = A
S[0..1] = AA
S[0..2] = AAA
S[0..3] = AAAA
Initially:
occ[A] = 0
occ[AA] = 0
occ[AAA] = 0
occ[AAAA] = 0
Step1: LPS Array of the following string denotes the length of the longest prefix which is also a suffix:
LPS[1] denotes in string AA, A is a suffix and also a prefix as LPS[1] = 1
LPS[2] denotes in string AAA, AA is a suffix and also a prefix as LPS[2] = 2
LPS[3] denotes in string AAAA, AAA is a suffix and also a prefix as LPS[3] = 3
Step 2:Add these occurrences of prefixes as suffixes to the answer in the occ[] array:
Values : Counted substrings
occ[A] = 1 : S[1]
occ[AA] = 1 : S[1..2]
occ[AAA] = 1 : S[1..3]
occ[AAAA] = 0 : NULL(as there is not a prefix “AAAA” which is also a suffix.
Step 3: Now traverse the string in reverse order starting from “AAA” (as the last value will always be 0 since the complete string is not a proper prefix).
Since, string “AAA” S[1..3] contains “AA” S[2..3] as well, which was not counted yet, therefore increment the occurrence of string “AA” in occ[“AA”] as occ[“AA”] += occ[“AAA”]. Below is the count for the same:
Values : Counted substrings
occ[A] = 1 : S[1]
occ[AA] = 2 : S[1..2], S[2..3]
occ[AAA] = 1 : S[1..3]
occ[AAAA] = 0 : NULL
Now string “AA” contains “A” as well, which was not counted yet, therefore increment the occurrence of string “A” in occ[“A”] as occ[“A”] += occ[“AA”]. Below is the count for the same:
Values : Counted substrings
occ[A] = 3 : S[1], S[2], S[3]
occ[AA] = 2 : S[1..2], S[2..3]
occ[AAA] = 1 : S[1..3]
occ[AAAA] = 0 : NULL
Step 4: At last add one to all occurrences for the original prefixes, which are not counted yet.
Values : Counted substrings
occ[A] = 4 : S[1], S[2], S[3], S[0]
occ[AA] = 3 : S[1..2], S[2..3], S[0..1]
occ[AAA] = 2 : S[1..3], S[0..2]
occ[AAAA] = 1 : S[0..3]
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Function to print the count of all // prefix in the given string void print(vector< int >& occ, string& s)
{ // Iterate over string s
for ( int i = 1; i <= int (s.size());
i++) {
// Print the prefix and their
// frequency
cout << s.substr(0, i)
<< " occurs "
<< occ[i]
<< " times."
<< endl;
}
} // Function to implement the LPS // array to store the longest prefix // which is also a suffix for every // substring of the string S vector< int > prefix_function(string& s)
{ // Array to store LPS values
vector< int > LPS(s.size());
// Value of lps[0] is 0
// by definition
LPS[0] = 0;
// Find the values of LPS[i] for
// the rest of the string using
// two pointers and DP
for ( int i = 1;
i < int (s.size());
i++) {
// Initially set the value
// of j as the longest
// prefix that is also a
// suffix for i as LPS[i-1]
int j = LPS[i - 1];
// Check if the suffix of
// length j+1 is also a prefix
while (j > 0 && s[i] != s[j]) {
j = LPS[j - 1];
}
// If s[i] = s[j] then, assign
// LPS[i] as j+1
if (s[i] == s[j]) {
LPS[i] = j + 1;
}
// If we reached j = 0, assign
// LPS[i] as 0 as there was no
// prefix equal to suffix
else {
LPS[i] = 0;
}
}
// Return the calculated
// LPS array
return LPS;
} // Function to count the occurrence // of all the prefix in the string S void count_occurrence(string& s)
{ int n = s.size();
// Call the prefix_function
// to get LPS
vector< int > LPS
= prefix_function(s);
// To store the occurrence of
// all the prefix
vector< int > occ(n + 1);
// Count all the suffixes that
// are also prefix
for ( int i = 0; i < n; i++) {
occ[LPS[i]]++;
}
// Add the occurrences of
// i to smaller prefixes
for ( int i = n - 1;
i > 0; i--) {
occ[LPS[i - 1]] += occ[i];
}
// Adding 1 to all occ[i] for all
// the original prefix
for ( int i = 0; i <= n; i++)
occ[i]++;
// Function Call to print the
// occurrence of all the prefix
print(occ, s);
} // Driver Code int main()
{ // Given String
string A = "ABACABA" ;
// Function Call
count_occurrence(A);
return 0;
} |
// Java program for // the above approach import java.util.*;
class GFG{
// Function to print the count // of all prefix in the // given String static void print( int [] occ,
String s)
{ // Iterate over String s
for ( int i = 1 ;
i <= s.length() - 1 ; i++)
{
// Print the prefix and their
// frequency
System.out.print(s.substring( 0 , i) +
" occurs " + occ[i] +
" times." + "\n" );
}
} // Function to implement the LPS // array to store the longest prefix // which is also a suffix for every // subString of the String S static int [] prefix_function(String s)
{ // Array to store LPS values
int []LPS = new int [s.length()];
// Value of lps[0] is 0
// by definition
LPS[ 0 ] = 0 ;
// Find the values of LPS[i] for
// the rest of the String using
// two pointers and DP
for ( int i = 1 ;
i < s.length(); i++)
{
// Initially set the value
// of j as the longest
// prefix that is also a
// suffix for i as LPS[i-1]
int j = LPS[i - 1 ];
// Check if the suffix of
// length j+1 is also a prefix
while (j > 0 &&
s.charAt(i) != s.charAt(j))
{
j = LPS[j - 1 ];
}
// If s[i] = s[j] then, assign
// LPS[i] as j+1
if (s.charAt(i) == s.charAt(j))
{
LPS[i] = j + 1 ;
}
// If we reached j = 0, assign
// LPS[i] as 0 as there was no
// prefix equal to suffix
else
{
LPS[i] = 0 ;
}
}
// Return the calculated
// LPS array
return LPS;
} // Function to count the occurrence // of all the prefix in the String S static void count_occurrence(String s)
{ int n = s.length();
// Call the prefix_function
// to get LPS
int [] LPS = prefix_function(s);
// To store the occurrence of
// all the prefix
int []occ = new int [n + 1 ];
// Count all the suffixes that
// are also prefix
for ( int i = 0 ; i < n; i++)
{
occ[LPS[i]]++;
}
// Add the occurrences of
// i to smaller prefixes
for ( int i = n - 1 ;
i > 0 ; i--)
{
occ[LPS[i - 1 ]] += occ[i];
}
// Adding 1 to all occ[i] for all
// the original prefix
for ( int i = 0 ; i <= n; i++)
occ[i]++;
// Function Call to print the
// occurrence of all the prefix
print(occ, s);
} // Driver Code public static void main(String[] args)
{ // Given String
String A = "ABACABA" ;
// Function Call
count_occurrence(A);
} } // This code is contributed by Princi Singh |
# Python3 program for the above approach # Function to print the count of all # prefix in the given string def Print (occ, s):
# Iterate over string s
for i in range ( 1 , len (s) + 1 ):
# Print the prefix and their
# frequency
print (s[ 0 : i], "occur" , occ[i], "times." )
# Function to implement the LPS # array to store the longest prefix # which is also a suffix for every # substring of the string S def prefix_function(s):
# Array to store LPS values
# Value of lps[0] is 0
# by definition
LPS = [ 0 for i in range ( len (s))]
# Find the values of LPS[i] for
# the rest of the string using
# two pointers and DP
for i in range ( 1 , len (s)):
# Initially set the value
# of j as the longest
# prefix that is also a
# suffix for i as LPS[i-1]
j = LPS[i - 1 ]
# Check if the suffix of
# length j+1 is also a prefix
while (j > 0 and s[i] ! = s[j]):
j = LPS[j - 1 ]
# If s[i] = s[j] then, assign
# LPS[i] as j+1
if (s[i] = = s[j]):
LPS[i] = j + 1
# If we reached j = 0, assign
# LPS[i] as 0 as there was no
# prefix equal to suffix
else :
LPS[i] = 0
# Return the calculated
# LPS array
return LPS
# Function to count the occurrence # of all the prefix in the string S def count_occurrence(s):
n = len (s)
# Call the prefix_function
# to get LPS
LPS = prefix_function(s)
# To store the occurrence of
# all the prefix
occ = [ 0 for i in range (n + 1 )]
# Count all the suffixes that
# are also prefix
for i in range (n):
occ[LPS[i]] + = 1
# Add the occurrences of
# i to smaller prefixes
for i in range (n - 1 , 0 , - 1 ):
occ[LPS[i - 1 ]] + = occ[i]
# Adding 1 to all occ[i] for all
# the original prefix
for i in range (n + 1 ):
occ[i] + = 1
# Function Call to print the
# occurrence of all the prefix
Print (occ, s)
# Driver Code # Given String A = "ABACABA"
# Function Call count_occurrence(A) # This code is contributed by avanitrachhadiya2155 |
// C# program for // the above approach using System;
class GFG{
// Function to print the // count of all prefix // in the given String static void print( int [] occ,
String s)
{ // Iterate over String s
for ( int i = 1;
i <= s.Length - 1; i++)
{
// Print the prefix and their
// frequency
Console.Write(s.Substring(0, i) +
" occurs " + occ[i] +
" times." + "\n" );
}
} // Function to implement the LPS // array to store the longest prefix // which is also a suffix for every // subString of the String S static int [] prefix_function(String s)
{ // Array to store LPS values
int []LPS = new int [s.Length];
// Value of lps[0] is 0
// by definition
LPS[0] = 0;
// Find the values of LPS[i] for
// the rest of the String using
// two pointers and DP
for ( int i = 1;
i < s.Length; i++)
{
// Initially set the value
// of j as the longest
// prefix that is also a
// suffix for i as LPS[i-1]
int j = LPS[i - 1];
// Check if the suffix of
// length j+1 is also a prefix
while (j > 0 && s[i] != s[j])
{
j = LPS[j - 1];
}
// If s[i] = s[j] then,
// assign LPS[i] as j+1
if (s[i] == s[j])
{
LPS[i] = j + 1;
}
// If we reached j = 0, assign
// LPS[i] as 0 as there was no
// prefix equal to suffix
else
{
LPS[i] = 0;
}
}
// Return the calculated
// LPS array
return LPS;
} // Function to count the occurrence // of all the prefix in the String S static void count_occurrence(String s)
{ int n = s.Length;
// Call the prefix_function
// to get LPS
int [] LPS = prefix_function(s);
// To store the occurrence of
// all the prefix
int []occ = new int [n + 1];
// Count all the suffixes that
// are also prefix
for ( int i = 0; i < n; i++)
{
occ[LPS[i]]++;
}
// Add the occurrences of
// i to smaller prefixes
for ( int i = n - 1;
i > 0; i--)
{
occ[LPS[i - 1]] += occ[i];
}
// Adding 1 to all occ[i] for all
// the original prefix
for ( int i = 0; i <= n; i++)
occ[i]++;
// Function Call to print the
// occurrence of all the prefix
print(occ, s);
} // Driver Code public static void Main(String[] args)
{ // Given String
String A = "ABACABA" ;
// Function Call
count_occurrence(A);
} } // This code is contributed by Amit Katiyar |
<script> // JavaScript program for the above approach
// Function to print the count of all
// prefix in the given string
const print = (occ, s) => {
// Iterate over string s
for (let i = 1; i <= s.length; i++) {
// Print the prefix and their
// frequency
document.write(`${s.substr(0, i)} occurs ${occ[i]} times.<br/>`);
}
}
// Function to implement the LPS
// array to store the longest prefix
// which is also a suffix for every
// substring of the string S
const prefix_function = (s) => {
// Array to store LPS values
let LPS = new Array(s.length).fill(0);
// Value of lps[0] is 0
// by definition
LPS[0] = 0;
// Find the values of LPS[i] for
// the rest of the string using
// two pointers and DP
for (let i = 1; i < s.length; i++) {
// Initially set the value
// of j as the longest
// prefix that is also a
// suffix for i as LPS[i-1]
let j = LPS[i - 1];
// Check if the suffix of
// length j+1 is also a prefix
while (j > 0 && s[i] != s[j]) {
j = LPS[j - 1];
}
// If s[i] = s[j] then, assign
// LPS[i] as j+1
if (s[i] == s[j]) {
LPS[i] = j + 1;
}
// If we reached j = 0, assign
// LPS[i] as 0 as there was no
// prefix equal to suffix
else {
LPS[i] = 0;
}
}
// Return the calculated
// LPS array
return LPS;
}
// Function to count the occurrence
// of all the prefix in the string S
const count_occurrence = (s) => {
let n = s.length;
// Call the prefix_function
// to get LPS
let LPS = prefix_function(s);
// To store the occurrence of
// all the prefix
let occ = new Array(n + 1).fill(0);
// Count all the suffixes that
// are also prefix
for (let i = 0; i < n; i++) {
occ[LPS[i]]++;
}
// Add the occurrences of
// i to smaller prefixes
for (let i = n - 1;
i > 0; i--) {
occ[LPS[i - 1]] += occ[i];
}
// Adding 1 to all occ[i] for all
// the original prefix
for (let i = 0; i <= n; i++)
occ[i]++;
// Function Call to print the
// occurrence of all the prefix
print(occ, s);
}
// Driver Code
// Given String
let A = "ABACABA" ;
// Function Call
count_occurrence(A);
// This code is contributed by rakeshsahni
</script> |
A occurs 4 times. AB occurs 2 times. ABA occurs 2 times. ABAC occurs 1 times. ABACA occurs 1 times. ABACAB occurs 1 times. ABACABA occurs 1 times.
Time Complexity: O(N2)
Auxiliary Space: O(N)