Encode given string by replacing substrings with prefix same as itself with *
Given string str of size N containing only lowercase English letters. The task is to encrypt the string such that the substrings having same prefix as itself are replaced by a *. Generate the encrypted string.
Note: If the string can be encrypted in multiple ways, find the smallest encrypted string.
Examples:
Input: str = “ababcababcd”
Output: ab*c*d
Explanation: The substring “ababc” starting from 5th index (0 based indexing) can be replaced by a ‘*’. So the string becomes “ababcababcd” -> “ababc*d”. Now the substring “ab” starting from 2nd index can again be replaced with a ‘*’. So the string becomes “ab*c*d”Input: str = “zzzzzzz”
Output: z*z*z
Explanation: The string can be encrypted in 2 ways: “z*z*z” and “z**zzz”. Out of the two “z*z*z” is smaller in length.
Approach: A simple solution to generate smallest encrypted string is to find the longest non-overlapping repeated substring and encrypt that substring first. To implement this use the following steps:
- Create a stack to store the encrypted string.
- Declare two pointers (i & j) to point to the 1st index and middle index respectively.
- Now start traversing the string and repeat the loop until the entire string is scanned. Follow steps mentioned below for each iteration:
- Compare both the substring from index i and j.
- If both substrings are equal, then repeat the same process on this substring and store the remaining string into stack.
- Else decrement the value of 2nd pointer ( j ) by 1.
- Now pop all the elements from the stack and append a symbol “*” then store it in a output string.
- Return the encrypted string.
Below is the implementation of the above approach.
C++
// C++ code to implement the above approach #include <bits/stdc++.h> using namespace std; // Function to generate the encrypted string string compress(string str) { // Stack to store encrypted string stack<string> st; // Variable to store length of string int N = str.length(); // Variable to point 1st and middle index int i = 0, j = N / 2; // Repeat the loop until // the entire string is checked while (j > 0) { int mid = j; // Compare the substring // from index 0 to mid-1 // with the rest of the substring // after mid. for (i = 0; i < mid && str[i] == str[j]; i++, j++) ; // If both substrings are equal // then repeat the same process // on this substring and store // the remaining string into stack if (i == mid) { st.push(str.substr(j, N - 1)); // Update the value of // string 'str' with the // longest repeating substring str = str.substr(0, i); // Set the new string length to n N = mid; // Initialize the 2nd pointer // from the mid of new string j = N / 2; } // If both substrings are not equal // then decrement the 2nd pointer by 1 else { j = mid - 1; } } // Pop all the elements from the stack // append a symbol '*' and store // in a output string while (!st.empty()) { str = str + "*" + st.top(); st.pop(); } return str; } // Driver code int main() { // Declare and initialize the string string str = "zzzzzzz" ; cout << compress(str) << "\n" ; return 0; } |
Java
// Java code to implement the above approach import java.util.*; class GFG{ // Function to generate the encrypted String static String compress(String str) { // Stack to store encrypted String Stack<String> st = new Stack<String>(); // Variable to store length of String int N = str.length(); // Variable to point 1st and middle index int i = 0 , j = N / 2 ; // Repeat the loop until // the entire String is checked while (j > 0 ) { int mid = j; // Compare the subString // from index 0 to mid-1 // with the rest of the subString // after mid. for (i = 0 ; i < mid && str.charAt(i) == str.charAt(j); i++, j++) ; // If both subStrings are equal // then repeat the same process // on this subString and store // the remaining String into stack if (i == mid) { st.add(str.substring(j, N)); // Update the value of // String 'str' with the // longest repeating subString str = str.substring( 0 , i); // Set the new String length to n N = mid; // Initialize the 2nd pointer // from the mid of new String j = N / 2 ; } // If both subStrings are not equal // then decrement the 2nd pointer by 1 else { j = mid - 1 ; } } // Pop all the elements from the stack // append a symbol '*' and store // in a output String while (!st.isEmpty()) { str = str + "*" + st.peek(); st.pop(); } return str; } // Driver code public static void main(String[] args) { // Declare and initialize the String String str = "zzzzzzz" ; System.out.print(compress(str)+ "\n" ); } } // This code is contributed by 29AjayKumar |
Python3
# Python code for the above approach # Function to generate the encrypted string def compress( str ): # Stack to store encrypted string st = [] # Variable to store length of string N = len ( str ) # Variable to point 1st and middle index i = 0 j = ( int )(N / 2 ) # Repeat the loop until # the entire string is checked while (j > 0 ): mid = j # Compare the substring # from index 0 to mid-1 # with the rest of the substring # after mid. i = 0 while ( str [i] = = str [j] and i < mid): i + = 1 j + = 1 # If both substrings are equal # then repeat the same process # on this substring and store # the remaining string into stack if (i = = mid): st.append( str [j:N]) # Update the value of # string 'str' with the # longest repeating substring str = str [ 0 :i] # Set the new string length to n N = mid # Initialize the 2nd pointer # from the mid of new string j = N / / 2 # If both substrings are not equal # then decrement the 2nd pointer by 1 else : j = mid - 1 # Pop all the elements from the stack # append a symbol '*' and store # in a output string while ( len (st) ! = 0 ): str = str + '*' + st[ len (st) - 1 ] st.pop() return str # Driver code # Declare and initialize the string str = "zzzzzzz" print (compress( str )) # This code is contributed by Saurabh jaiswal |
C#
// C# code to implement the above approach using System; using System.Collections.Generic; public class GFG{ // Function to generate the encrypted String static String compress(String str) { // Stack to store encrypted String Stack<String> st = new Stack<String>(); // Variable to store length of String int N = str.Length; // Variable to point 1st and middle index int i = 0, j = N / 2; // Repeat the loop until // the entire String is checked while (j > 0) { int mid = j; // Compare the subString // from index 0 to mid-1 // with the rest of the subString // after mid. for (i = 0; i < mid && str[i] == str[j]; i++, j++) ; // If both subStrings are equal // then repeat the same process // on this subString and store // the remaining String into stack if (i == mid) { st.Push(str.Substring(j, N-j)); // Update the value of // String 'str' with the // longest repeating subString str = str.Substring(0, i); // Set the new String length to n N = mid; // Initialize the 2nd pointer // from the mid of new String j = N / 2; } // If both subStrings are not equal // then decrement the 2nd pointer by 1 else { j = mid - 1; } } // Pop all the elements from the stack // append a symbol '*' and store // in a output String while (st.Count!=0) { str = str + "*" + st.Peek(); st.Pop(); } return str; } // Driver code public static void Main(String[] args) { // Declare and initialize the String String str = "zzzzzzz" ; Console.Write(compress(str)+ "\n" ); } } // This code is contributed by shikhasingrajput |
Javascript
<script> // JavaScript code for the above approach // Function to generate the encrypted string function compress(str) { // Stack to store encrypted string let st = []; // Variable to store length of string let N = str.length; // Variable to point 1st and middle index let i = 0, j = Math.floor(N / 2); // Repeat the loop until // the entire string is checked while (j > 0) { let mid = j; // Compare the substring // from index 0 to mid-1 // with the rest of the substring // after mid. for (i = 0; i < mid && str[i] == str[j]; i++, j++) ; // If both substrings are equal // then repeat the same process // on this substring and store // the remaining string into stack if (i == mid) { st.push(str.slice(j, N)); // Update the value of // string 'str' with the // longest repeating substring str = str.slice(0, i); // Set the new string length to n N = mid; // Initialize the 2nd pointer // from the mid of new string j = Math.floor(N / 2); } // If both substrings are not equal // then decrement the 2nd pointer by 1 else { j = mid - 1; } } // Pop all the elements from the stack // append a symbol '*' and store // in a output string while (st.length != 0) { str = str + '*' + st[st.length - 1]; st.pop(); } return str; } // Driver code // Declare and initialize the string let str = "zzzzzzz" ; document.write(compress(str) + '<br>' ); // This code is contributed by Potta Lokesh </script> |
z*z*z
Time Complexity: O(N. Log(N))
Auxiliary Space: O(N)
Please Login to comment...