Skip to content
Related Articles

Related Articles

Improve Article
Save Article
Like Article

Maximize count of occurrences of S2 in S1 as a subsequence by concatenating N1 and N2 times respectively

  • Last Updated : 24 Jun, 2021

Given two strings S1, S2 of length N and M respectively, and two positive integers N1 and N2, the task is to find the maximum count of non-overlapping subsequences of S1 which are equal to S2 by concatenating the string s1, n1 times and the string s2, n2 times.

Examples:

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.

Input: S1 = “acb”, S2 = “ab”, N1 = 4, N2 = 2 
Output:
Explanation: 
Concatenating the string S1, N1 ( = 4) times modifies S1 to “acbacbacbacb”. 
Concatenating the string S2, N2 ( = 2) times modifies S2 to “abab”. 
Since the string S2 occurs twice as a non-overlapping subsequence in S1, the required output is 2.



Input: S1 = “abc”, S2 = “a”, N1 = 1, N2 = 1 
Output: 1

Approach: The problem can be solved using the concept of checking if a string is a subsequence of another string or not
Follow the steps below to solve the problem:

  • Iterate over the characters of the string S2 and check if all the characters of S2 are present in the string S1 or not. If found to be false, then no such subsequence of S1 is possible which can be made equal to S2 by concatenating the string S1, N1 times and the string S2, N2 times.
  • Iterate over the characters of the string S1, N1 times circularly. For every ith index, check if any subsequence of S1 exists up to ith index, which is equal to S2 or not. If found to be true, then increment the count.
  • Finally, print the count obtained divided by N2 as the required answer, after performing the above operations.

Below is the implementation of the above approach:

C++




// C++ program for the above approach
#include <bits/stdc++.h>
 
using namespace std;
 
// Function to count maximum number of
// occurrences of s2 as subsequence in s1
// by concatenating s1, n1 times and s2, n2 times
int getMaxRepetitions(string s1, int n1,
                      string s2, int n2)
{
 
  int temp1[26] = {0}, temp2[26] = {0};
 
  for(char i:s1) temp1[i - 'a']++;
 
  for(char i:s2) temp2[i - 'a']++;
 
  for(int i = 0; i < 26; i++)
  {
    if(temp2[i] > temp1[i]) return 0;
  }
 
  // Stores number of times
  // s1 is traversed
  int s1_reps = 0;
 
  // Stores number of times
  // s2 is traversed
  int s2_reps = 0;
 
  // Mapping index of s2 to number
  // of times s1 and s2 are traversed
  map<int, pair<int, int> > s2_index_to_reps;
  s2_index_to_reps[0] = {0, 0};
 
  // Stores index of s1 circularly
  int i = 0;
 
  // Stores index of s2 circularly
  int j = 0;
 
  // Traverse the string s1, n1 times
  while (s1_reps < n1){
 
    // If current character of both
    // the string are equal
    if (s1[i] == s2[j])
 
      // Update j
      j += 1;
 
    // Update i
    i += 1;
 
    // If j is length of s2
    if (j == s2.size())
    {
      // Update j for
      // circular traversal
      j = 0;
 
      // Update s2_reps
      s2_reps += 1;
    }
 
    // If i is length of s1
    if (i == s1.size())
    {
 
      // Update i for
      // circular traversal
      i = 0;
 
      // Update s1_reps
      s1_reps += 1;
 
      // If already mapped j
      // to (s1_reps, s2_reps)
      if (s2_index_to_reps.find(j) !=
          s2_index_to_reps.end())
        break;
 
      // Mapping j to (s1_reps, s2_reps)
      s2_index_to_reps[j] = {s1_reps, s2_reps};
    }
  }
 
  // If s1 already traversed n1 times
  if (s1_reps == n1)
    return s2_reps / n2;
 
  // Otherwis, traverse string s1 by multiple of
  // s1_reps and update both s1_reps and s2_reps
  int initial_s1_reps = s2_index_to_reps[j].first ,
  initial_s2_reps = s2_index_to_reps[j].second;
  int loop_s1_reps = s1_reps - initial_s1_reps;
  int loop_s2_reps = s2_reps - initial_s2_reps;
  int loops = (n1 - initial_s1_reps);
 
 
  // Update s2_reps
  s2_reps = initial_s2_reps + loops * loop_s2_reps;
 
  // Update s1_reps
  s1_reps = initial_s1_reps + loops * loop_s1_reps;
 
  // If s1 is traversed less than n1 times
  while (s1_reps < n1)
  {
 
    // If current character in both
    // the string are equal
    if (s1[i] == s2[j])
 
      // Update j
      j += 1;
 
    // Update i
    i += 1;
 
    // If i is length of s1
    if (i == s1.size())
    {
 
      // Update i for circular traversal
      i = 0;
 
      // Update s1_reps
      s1_reps += 1;
    }
 
    // If j is length of ss
    if (j == s2.size())
    {
 
      // Update j for circular traversal
      j = 0;
 
      // Update s2_reps
      s2_reps += 1;
    }
  }
  return s2_reps / n2;
}
 
// Driver Code
int main()
{
  string s1 = "acb";
  int n1 = 4;
  string s2 = "ab";
  int n2 = 2;
 
  cout << (getMaxRepetitions(s1, n1, s2, n2));
 
  return 0;
}
 
// This code is contributed by mohit kumar 29.

Java




// Java program for the above approach
import java.io.*;
import java.lang.*;
import java.util.*;
 
class GFG{
 
// Function to count maximum number of
// occurrences of s2 as subsequence in s1
// by concatenating s1, n1 times and s2, n2 times
static int getMaxRepetitions(String s1, int n1,
                             String s2, int n2)
{
    int temp1[] = new int[26], temp2[] = new int[26];
 
    for(char i : s1.toCharArray())
        temp1[i - 'a']++;
 
    for(char i : s2.toCharArray())
        temp2[i - 'a']++;
 
    for(int i = 0; i < 26; i++)
    {
        if (temp2[i] > temp1[i])
            return 0;
    }
 
    // Stores number of times
    // s1 is traversed
    int s1_reps = 0;
 
    // Stores number of times
    // s2 is traversed
    int s2_reps = 0;
 
    // Mapping index of s2 to number
    // of times s1 and s2 are traversed
    HashMap<Integer, int[]> s2_index_to_reps = new HashMap<>();
    s2_index_to_reps.put(0, new int[] { 0, 0 });
 
    // Stores index of s1 circularly
    int i = 0;
 
    // Stores index of s2 circularly
    int j = 0;
 
    // Traverse the string s1, n1 times
    while (s1_reps < n1)
    {
         
        // If current character of both
        // the string are equal
        if (s1.charAt(i) == s2.charAt(j))
 
            // Update j
            j += 1;
 
        // Update i
        i += 1;
 
        // If j is length of s2
        if (j == s2.length())
        {
             
            // Update j for
            // circular traversal
            j = 0;
 
            // Update s2_reps
            s2_reps += 1;
        }
 
        // If i is length of s1
        if (i == s1.length())
        {
             
            // Update i for
            // circular traversal
            i = 0;
 
            // Update s1_reps
            s1_reps += 1;
 
            // If already mapped j
            // to (s1_reps, s2_reps)
            if (!s2_index_to_reps.containsKey(j))
                break;
 
            // Mapping j to (s1_reps, s2_reps)
            s2_index_to_reps.put(
                j, new int[] { s1_reps, s2_reps });
        }
    }
 
    // If s1 already traversed n1 times
    if (s1_reps == n1)
        return s2_reps / n2;
 
    // Otherwis, traverse string s1 by multiple of
    // s1_reps and update both s1_reps and s2_reps
    int initial_s1_reps = s2_index_to_reps.get(j)[0],
        initial_s2_reps = s2_index_to_reps.get(j)[1];
    int loop_s1_reps = s1_reps - initial_s1_reps;
    int loop_s2_reps = s2_reps - initial_s2_reps;
    int loops = (n1 - initial_s1_reps);
 
    // Update s2_reps
    s2_reps = initial_s2_reps + loops * loop_s2_reps;
 
    // Update s1_reps
    s1_reps = initial_s1_reps + loops * loop_s1_reps;
 
    // If s1 is traversed less than n1 times
    while (s1_reps < n1)
    {
         
        // If current character in both
        // the string are equal
        if (s1.charAt(i) == s2.charAt(j))
 
            // Update j
            j += 1;
 
        // Update i
        i += 1;
 
        // If i is length of s1
        if (i == s1.length())
        {
             
            // Update i for circular traversal
            i = 0;
 
            // Update s1_reps
            s1_reps += 1;
        }
 
        // If j is length of ss
        if (j == s2.length())
        {
             
            // Update j for circular traversal
            j = 0;
 
            // Update s2_reps
            s2_reps += 1;
        }
    }
    return s2_reps / n2;
}
 
// Driver Code
public static void main(String[] args)
{
    String s1 = "acb";
    int n1 = 4;
    String s2 = "ab";
    int n2 = 2;
 
    System.out.println(
        getMaxRepetitions(s1, n1, s2, n2));
}
}
 
// This code is contributed by Kingash

Python3




# Python3 program for the above approach
 
# Function to count maximum number of
# occurrences of s2 as subsequence in s1
# by concatenating s1, n1 times and s2, n2 times
def getMaxRepetitions(s1, n1, s2, n2):
 
    # If all the characters of s2 are not present in s1
    if any(c for c in set(s2) if c not in set(s1)):
        return 0
 
    # Stores number of times
    # s1 is traversed
    s1_reps = 0
 
    # Stores number of times
    # s2 is traversed
    s2_reps = 0
 
    # Mapping index of s2 to number
    # of times s1 and s2 are traversed
    s2_index_to_reps = { 0 : (0, 0)}
 
    # Stores index of s1 circularly
    i = 0
 
    # Stores index of s2 circularly
    j = 0
 
    # Traverse the string s1, n1 times
    while s1_reps < n1:
 
        # If current character of both
        # the string are equal
        if s1[i] == s2[j]:
         
            # Update j
            j += 1
 
        # Update i   
        i += 1
 
        # If j is length of s2
        if j == len(s2):
             
            # Update j for
            # circular traversal
            j = 0
 
            # Update s2_reps
            s2_reps += 1
 
        # If i is length of s1
        if i == len(s1):
 
            # Update i for
            # circular traversal
            i = 0
 
            # Update s1_reps
            s1_reps += 1
 
            # If already mapped j
            # to (s1_reps, s2_reps)
            if j in s2_index_to_reps:
                break
 
            # Mapping j to (s1_reps, s2_reps)   
            s2_index_to_reps[j] = (s1_reps, s2_reps)
 
    # If s1 already traversed n1 times
    if s1_reps == n1:
        return s2_reps // n2
 
    # Otherwis, traverse string s1 by multiple of
    # s1_reps and update both s1_reps and s2_reps
 
    initial_s1_reps, initial_s2_reps = s2_index_to_reps[j]
    loop_s1_reps = s1_reps - initial_s1_reps
    loop_s2_reps = s2_reps - initial_s2_reps
    loops = (n1 - initial_s1_reps)
 
 
    # Update s2_reps
    s2_reps = initial_s2_reps + loops * loop_s2_reps
 
    # Update s1_reps
    s1_reps = initial_s1_reps + loops * loop_s1_reps
 
    # If s1 is traversed less than n1 times
    while s1_reps < n1:
 
        # If current character in both
        # the string are equal
        if s1[i] == s2[j]:
 
            # Update j
            j += 1
 
        # Update i   
        i += 1
         
        # If i is length of s1
        if i == len(s1):
 
            # Update i for circular traversal
            i = 0
 
            # Update s1_reps
            s1_reps += 1
             
        # If j is length of ss
        if j == len(s2):
 
            # Update j for circular traversal
            j = 0
 
            # Update s2_reps
            s2_reps += 1
 
    return s2_reps // n2
 
# Driver Code
if __name__ == '__main__':
    s1 = "acb"
    n1 = 4
    s2 = "ab"
    n2 = 2
 
    print(getMaxRepetitions(s1, n1, s2, n2))

Javascript




<script>
// Javascript program for the above approach
 
// Function to count maximum number of
// occurrences of s2 as subsequence in s1
// by concatenating s1, n1 times and s2, n2 times
function getMaxRepetitions(s1,n1,s2,n2)
{
    let temp1 = new Array(26);
    let temp2 = new Array(26);
     
    for(let i = 0; i < 26; i++)
    {
        temp1[i] = 0;
        temp2[i] = 0;
    }
  
    for(let i = 0; i < s1.split("").length; i++)
        temp1[s1[i].charCodeAt(0) - 'a'.charCodeAt(0)]++;
  
    for(let i = 0; i < s2.split("").length; i++)
        temp2[s2[i].charCodeAt(0) - 'a'.charCodeAt(0)]++;
  
    for(let i = 0; i < 26; i++)
    {
        if (temp2[i] > temp1[i])
            return 0;
    }
  
    // Stores number of times
    // s1 is traversed
    let s1_reps = 0;
  
    // Stores number of times
    // s2 is traversed
    let s2_reps = 0;
  
    // Mapping index of s2 to number
    // of times s1 and s2 are traversed
    let s2_index_to_reps = new Map();
    s2_index_to_reps.set(0, [ 0, 0 ]);
  
    // Stores index of s1 circularly
    let i = 0;
  
    // Stores index of s2 circularly
    let j = 0;
  
    // Traverse the string s1, n1 times
    while (s1_reps < n1)
    {
          
        // If current character of both
        // the string are equal
        if (s1[i] == s2[j])
  
            // Update j
            j += 1;
  
        // Update i
        i += 1;
  
        // If j is length of s2
        if (j == s2.length)
        {
              
            // Update j for
            // circular traversal
            j = 0;
  
            // Update s2_reps
            s2_reps += 1;
        }
  
        // If i is length of s1
        if (i == s1.length)
        {
              
            // Update i for
            // circular traversal
            i = 0;
  
            // Update s1_reps
            s1_reps += 1;
  
            // If already mapped j
            // to (s1_reps, s2_reps)
            if (!s2_index_to_reps.has(j))
                break;
  
            // Mapping j to (s1_reps, s2_reps)
            s2_index_to_reps.set(
                j, [s1_reps, s2_reps ]);
        }
    }
  
    // If s1 already traversed n1 times
    if (s1_reps == n1)
        return s2_reps / n2;
  
    // Otherwis, traverse string s1 by multiple of
    // s1_reps and update both s1_reps and s2_reps
    let initial_s1_reps = s2_index_to_reps.get(j)[0],
        initial_s2_reps = s2_index_to_reps.get(j)[1];
    let loop_s1_reps = s1_reps - initial_s1_reps;
    let loop_s2_reps = s2_reps - initial_s2_reps;
    let loops = (n1 - initial_s1_reps);
  
    // Update s2_reps
    s2_reps = initial_s2_reps + loops * loop_s2_reps;
  
    // Update s1_reps
    s1_reps = initial_s1_reps + loops * loop_s1_reps;
  
    // If s1 is traversed less than n1 times
    while (s1_reps < n1)
    {
          
        // If current character in both
        // the string are equal
        if (s1[i] == s2[j])
  
            // Update j
            j += 1;
  
        // Update i
        i += 1;
  
        // If i is length of s1
        if (i == s1.length)
        {
              
            // Update i for circular traversal
            i = 0;
  
            // Update s1_reps
            s1_reps += 1;
        }
  
        // If j is length of ss
        if (j == s2.length)
        {
              
            // Update j for circular traversal
            j = 0;
  
            // Update s2_reps
            s2_reps += 1;
        }
    }
    return s2_reps / n2;
}
 
// Driver Code
let s1 = "acb";
let n1 = 4;
let s2 = "ab";
let n2 = 2;
document.write(getMaxRepetitions(s1, n1, s2, n2));
 
// This code is contributed by unknown2108
</script>
Output: 
2

 

Time Complexity: O((N + M) * n1) 
Auxiliary Space:O(1)




My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!