Count unique substrings of a string S present in a wraparound string
Last Updated :
14 Apr, 2023
Given a string S which is an infinite wraparound string of the string “abcdefghijklmnopqrstuvwxyz”, the task is to count the number of unique non-empty substrings of a string p are present in s.
Examples:
Input: S = “zab”
Output: 6
Explanation: All possible substrings are “z”, “a”, “b”, “za”, “ab”, “zab”.
Input: S = “cac”
Output: 2
Explanation: All possible substrings are “a” and “c” only.
Approach: Follow the steps below to solve the problem
- Iterate over each character of the string
- Initialize an auxiliary array arr[] of size 26, to store the current length of substring that is present in string S starting from each character of string P.
- Initialize a variable, say curLen, which stores the length of substring present in P including the current character if the current character is not a part of the previous substring.
- Initialize a variable, say ans, to store the unique count of non-empty substrings of p present in S.
- Iterate over the characters of the string and check for the following two cases:
- Check if the current character can be added with previous substring to form the required substring or not.
- Add the difference of curLen and arr[curr] to ans if (curLen + 1) is greater than arr[curr] to avoid repetition of substrings.
- Print the value of ans.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int findSubstringInWraproundString(string p)
{
int ans = 0;
int curLen = 0;
int arr[26] = { 0 };
for ( int i = 0; i < ( int )p.length(); i++) {
int curr = p[i] - 'a' ;
if (i > 0
&& (p[i - 1]
!= ((curr + 26 - 1) % 26 + 'a' ))) {
curLen = 0;
}
curLen++;
if (curLen > arr[curr]) {
ans += (curLen - arr[curr]);
arr[curr] = curLen;
}
}
cout << ans;
}
int main()
{
string p = "zab" ;
findSubstringInWraproundString(p);
return 0;
}
|
Java
import java.util.*;
class GFG
{
static void findSubstringInWraproundString(String p)
{
int ans = 0 ;
int curLen = 0 ;
int arr[] = new int [ 26 ];
for ( int i = 0 ; i < p.length(); i++)
{
int curr = p.charAt(i) - 'a' ;
if (i > 0
&& (p.charAt(i - 1 )
!= ((curr + 26 - 1 ) % 26 + 'a' )))
{
curLen = 0 ;
}
curLen++;
if (curLen > arr[curr])
{
ans += (curLen - arr[curr]);
arr[curr] = curLen;
}
}
System.out.println(ans);
}
public static void main(String args[])
{
String p = "zab" ;
findSubstringInWraproundString(p);
}
}
|
Python3
def findSubstringInWraproundString(p) :
ans = 0
curLen = 0
arr = [ 0 ] * 26
for i in range ( 0 , len (p)) :
curr = ord (p[i]) - ord ( 'a' )
if (i > 0 and ( ord (p[i - 1 ]) ! = ((curr + 26 - 1 ) % 26 + ord ( 'a' )))) :
curLen = 0
curLen + = 1
if (curLen > arr[curr]) :
ans + = (curLen - arr[curr])
arr[curr] = curLen
print (ans)
p = "zab"
findSubstringInWraproundString(p)
|
C#
using System;
class GFG
{
static void findSubstringInWraproundString( string p)
{
int ans = 0;
int curLen = 0;
int [] arr = new int [26];
for ( int i = 0; i < ( int )p.Length; i++)
{
int curr = p[i] - 'a' ;
if (i > 0 && (p[i - 1] != ((curr + 26 - 1) % 26 + 'a' )))
{
curLen = 0;
}
curLen++;
if (curLen > arr[curr])
{
ans += (curLen - arr[curr]);
arr[curr] = curLen;
}
}
Console.Write(ans);
}
static void Main()
{
string p = "zab" ;
findSubstringInWraproundString(p);
}
}
|
Javascript
<script>
function findSubstringInWraproundString(p)
{
let ans = 0;
let curLen = 0;
let arr = new Array(26);
arr.fill(0);
for (let i = 0; i < p.length; i++)
{
let curr = p[i].charCodeAt() - 'a' .charCodeAt();
if (i > 0 && (p[i - 1].charCodeAt() != ((curr + 26 - 1) % 26 + 'a' .charCodeAt())))
{
curLen = 0;
}
curLen++;
if (curLen > arr[curr])
{
ans += (curLen - arr[curr]);
arr[curr] = curLen;
}
}
document.write(ans);
}
let p = "zab" ;
findSubstringInWraproundString(p);
</script>
|
Time Complexity: O(N)
Auxiliary Space: O(1)
Method 2:
Approach Steps:
- Initialize a dictionary to store the count of distinct substrings starting with each letter of the English alphabet.
- Initialize the length of the longest increasing substring ending at each position in the given string ‘p’ to 0.
- Iterate over the characters of ‘p’ and update the length of the longest increasing substring ending at each position using dynamic programming.
- Update the count of distinct substrings starting with each letter of ‘p’ based on the length of the longest increasing substring ending at each position.
- Return the sum of counts for all letters.
C++
#include <iostream>
#include <cstring>
using namespace std;
int countSubstringsInWraparoundString(string p) {
int count[26];
memset (count, 0, sizeof (count));
int len_inc_substring[p.length()];
memset (len_inc_substring, 0, sizeof (len_inc_substring));
for ( int i = 0; i < p.length(); i++) {
if (i > 0 && (p[i] - p[i-1] + 26) % 26 == 1) {
len_inc_substring[i] = len_inc_substring[i-1] + 1;
}
else {
len_inc_substring[i] = 1;
}
count[p[i]- 'a' ] = max(count[p[i]- 'a' ], len_inc_substring[i]);
}
int total_count = 0;
for ( int i = 0; i < 26; i++) {
total_count += count[i];
}
return total_count;
}
int main() {
string p = "zab" ;
cout << countSubstringsInWraparoundString(p) << endl;
return 0;
}
|
Java
import java.util.Arrays;
public class Main {
public static int countSubstringsInWraparoundString(String p) {
int [] count = new int [ 26 ];
Arrays.fill(count, 0 );
int [] len_inc_substring = new int [p.length()];
Arrays.fill(len_inc_substring, 0 );
for ( int i = 0 ; i < p.length(); i++) {
if (i > 0 && (p.charAt(i) - p.charAt(i- 1 ) + 26 ) % 26 == 1 ) {
len_inc_substring[i] = len_inc_substring[i- 1 ] + 1 ;
}
else {
len_inc_substring[i] = 1 ;
}
count[p.charAt(i)- 'a' ] = Math.max(count[p.charAt(i)- 'a' ], len_inc_substring[i]);
}
int total_count = 0 ;
for ( int i = 0 ; i < 26 ; i++) {
total_count += count[i];
}
return total_count;
}
public static void main(String[] args) {
String p = "zab" ;
System.out.println(countSubstringsInWraparoundString(p));
}
}
|
Python3
def countSubstringsInWraparoundString(p):
count = { chr (i): 0 for i in range ( ord ( 'a' ), ord ( 'z' ) + 1 )}
len_inc_substring = [ 0 ] * len (p)
for i in range ( len (p)):
if i > 0 and ( ord (p[i]) - ord (p[i - 1 ])) % 26 = = 1 :
len_inc_substring[i] = len_inc_substring[i - 1 ] + 1
else :
len_inc_substring[i] = 1
count[p[i]] = max (count[p[i]], len_inc_substring[i])
return sum (count.values())
p = "zab"
print (countSubstringsInWraparoundString(p))
|
C#
using System;
public class MainClass {
public static int
CountSubstringsInWraparoundString( string p)
{
int [] count = new int [26];
Array.Fill(count, 0);
int [] len_inc_substring = new int [p.Length];
Array.Fill(len_inc_substring, 0);
for ( int i = 0; i < p.Length; i++) {
if (i > 0 && (p[i] - p[i - 1] + 26) % 26 == 1) {
len_inc_substring[i]
= len_inc_substring[i - 1] + 1;
}
else {
len_inc_substring[i] = 1;
}
count[p[i] - 'a' ] = Math.Max(
count[p[i] - 'a' ], len_inc_substring[i]);
}
int total_count = 0;
for ( int i = 0; i < 26; i++) {
total_count += count[i];
}
return total_count;
}
public static void Main()
{
string p = "zab" ;
Console.WriteLine(CountSubstringsInWraparoundString(
p));
}
}
|
Javascript
function countSubstringsInWraparoundString(p) {
let count = {};
for (let i = 'a' .charCodeAt(0); i <= 'z' .charCodeAt(0); i++) {
count[String.fromCharCode(i)] = 0;
}
let len_inc_substring = new Array(p.length).fill(0);
for (let i = 0; i < p.length; i++) {
if (i > 0 && (p.charCodeAt(i) - p.charCodeAt(i-1) + 26) % 26 == 1) {
len_inc_substring[i] = len_inc_substring[i-1] + 1;
} else {
len_inc_substring[i] = 1;
}
count[p[i]] = Math.max(count[p[i]], len_inc_substring[i]);
}
return Object.values(count).reduce((a,b) => a+b);
}
let p = "zab" ;
console.log(countSubstringsInWraparoundString(p));
|
Time Complexity:
The time complexity of this approach is O(n), where n is the length of the input string ‘p’. This is because we iterate over the characters of ‘p’ only once.
Auxiliary Space:
The auxiliary space of this approach is O(26), which is constant. This is because we use a dictionary to store the count of distinct substrings starting with each letter of the English alphabet, and the size of the dictionary is fixed at 26. We also use a list of size n to store the length of the longest increasing substring ending at each position in ‘p’. Therefore, the total auxiliary space used by the algorithm is O(26 + n), which is equivalent to O(n).
Share your thoughts in the comments
Please Login to comment...