Encode given string by replacing substrings with prefix same as itself with * - GeeksforGeeks

29 Dec, 2021
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*dExplanation: 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*zExplanation: 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.
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++
Java
Python3
C#
Javascript
// C++ code to implement the above approach#include <bits/stdc++.h>using namespace std;  // Function to generate the encrypted stringstring 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 codeint main(){    // Declare and initialize the string    string str = "zzzzzzz";      cout << compress(str) << "\n";    return 0;}
// Java code to implement the above approach  import java.util.*;  class GFG{  // Function to generate the encrypted Stringstatic 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 codepublic 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
# Python code for the above approach  # Function to generate the encrypted stringdef 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 stringstr = "zzzzzzz"print(compress(str))  # This code is contributed by Saurabh jaiswal
// C# code to implement the above approachusing System;using System.Collections.Generic;  public class GFG{  // Function to generate the encrypted Stringstatic 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 codepublic static void Main(String[] args){    // Declare and initialize the String    String str = "zzzzzzz";      Console.Write(compress(str)+ "\n");}}  // This code is contributed by shikhasingrajput
<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)
 
lokeshpotta20
_saurabh_jaiswal
29AjayKumar
shikhasingrajput
Algo-Geek 2021
encoding-decoding
prefix
substring
Algo Geek
Stack
Strings
Strings
Stack
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
Check if the given string is valid English word or not
Sort strings on the basis of their numeric part
Divide given number into two even parts
Smallest set of vertices to visit all nodes of the given Graph
Count of Palindrome Strings in given Array of strings
Stack Data Structure (Introduction and Program)
Stack Class in Java
Stack in Python
Check for Balanced Brackets in an expression (well-formedness) using Stack
Stack | Set 2 (Infix to Postfix)