Open In App

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

Last Updated : 29 Dec, 2021
Improve
Improve
Like Article
Like
Save
Share
Report

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)

 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads