Skip to content
Related Articles
Get the best out of our app
GFG App
Open App
geeksforgeeks
Browser
Continue

Related Articles

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

Improve Article
Save Article
Like Article
Improve Article
Save Article
Like Article

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>


 
 

Output

z*z*z

 

Time Complexity: O(N. Log(N))
Auxiliary Space: O(N)

 


My Personal Notes arrow_drop_up
Last Updated : 29 Dec, 2021
Like Article
Save Article
Similar Reads
Related Tutorials