Given a string S, the task is to find the length of the shortest compressed string. The string can be compressed in the following way:
- If S = “ABCDABCD”, then the string can be compressed as (ABCD)2, so the length of the compressed string will be 4.
- If S = “AABBCCDD” then the string compressed form will be A2B2C2D2 therefore, the length of the compressed string will be 4.
Examples:
Input: S = “aaba”
Output: 3
Explanation : It can be rewritten as a2ba therefore the answer will be 3.Input: S = “aaabaaabccdaaabaaabccd”
Output: 4
Explanation: The string can be rewritten as (((a)3b)2(c)2d)2. Therefore, the answer will be 4.
Approach: The problem can be solved using dynamic programming because it has Optimal Substructure and Overlapping Subproblems. Follow the steps below to solve the problem:
- Initialize a dp[][] vector, where dp[i][j] stores the length of compressed substring s[i], s[i+1], …, s[j].
-
Iterate in the range [1, N] using the variable l and perform the following steps:
-
Iterate in the range [0, N-l] using the variable i and perform the following steps:
- Initialize a variable say, j as i+l-1.
- If i is equal to j, then update dp[i][j] as 1 and continue.
- Iterate in the range [i, j-1] using the variable k and update dp[i][j] as min of dp[i][j] and dp[i][k] + dp[k][j].
- Initialize a variable say, temp as s.substr(i, l).
- Then, find the longest prefix that is also the suffix of the substring temp.
- If the substring is of the form of dp[i][k]^n(l%(l – pref[l-1]) = 0), then update the value of dp[i][j] as min(dp[i][j], dp[i][i + (l-pref[l-1] – 1)]).
-
Iterate in the range [0, N-l] using the variable i and perform the following steps:
- Finally, print the value of dp[0][N-1] as the answer.
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Prefix function to calculate // longest prefix that is also // the suffix of the substring S vector< int > prefix_function(string s)
{ int n = ( int )s.length();
vector< int > pi(n);
for ( int i = 1; i < n; i++) {
int j = pi[i - 1];
while (j > 0 && s[i] != s[j])
j = pi[j - 1];
if (s[i] == s[j])
j++;
pi[i] = j;
}
return pi;
} // Function to find the length of the // shortest compressed string void minLength(string s, int n)
{ // Declare a 2D dp vector
vector<vector< int > > dp(n + 1, vector< int >(n + 1, 10000));
// Traversing substring on the basis of length
for ( int l = 1; l <= n; l++) {
// For loop for each substring of length l
for ( int i = 0; i < n - l + 1; i++) {
// Second substring coordinate
int j = i + l - 1;
// If the length of the string is 1
// then dp[i][j] = 1
if (i == j) {
dp[i][j] = 1;
continue ;
}
// Finding smallest dp[i][j] value
// by breaking it in two substrings
for ( int k = i; k < j; k++) {
dp[i][j] = min(dp[i][j],
dp[i][k] + dp[k + 1][j]);
}
// Substring starting with i of length L
string temp = s.substr(i, l);
// Prefix function of the substring temp
auto pref = prefix_function(temp);
// Checking if the substring is
// of the form of dp[i][k]^n
if (l % (l - pref[l - 1]) == 0) {
// If yes, check if dp[i][k] is
// less than dp[i][j]
dp[i][j] = min(dp[i][j],
dp[i][i + (l - pref[l - 1] - 1)]);
}
}
}
// Finally, print the required answer
cout << dp[0][n - 1] << endl;
} // Driver Code int main()
{ // Given Input
int n = 4;
string s = "aaba" ;
// Function Call
minLength(s, n);
} |
/*package whatever //do not write package name here */ import java.io.*;
import java.util.*;
class GFG {
// Java program for the above approach
// Prefix function to calculate
// longest prefix that is also
// the suffix of the substring S
static int [] prefix_function(String s)
{
int n = s.length();
int [] pi = new int [n];
for ( int i = 1 ; i < n; i++) {
int j = pi[i - 1 ];
while (j > 0 && s.charAt(i) != s.charAt(j))
j = pi[j - 1 ];
if (s.charAt(i) == s.charAt(j))
j++;
pi[i] = j;
}
return pi;
}
// Function to find the length of the
// shortest compressed string
static void minLength(String s, int n)
{
// Declare a 2D dp vector
int dp[][] = new int [n + 1 ][n + 1 ];
for ( int [] row : dp){
Arrays.fill(row, 10000 );
}
// Traversing substring on the basis of length
for ( int l = 1 ; l <= n; l++) {
// For loop for each substring of length l
for ( int i = 0 ; i < n - l + 1 ; i++) {
// Second substring coordinate
int j = i + l - 1 ;
// If the length of the string is 1
// then dp[i][j] = 1
if (i == j) {
dp[i][j] = 1 ;
continue ;
}
// Finding smallest dp[i][j] value
// by breaking it in two substrings
for ( int k = i; k < j; k++) {
dp[i][j] = Math.min(dp[i][j],
dp[i][k] + dp[k + 1 ][j]);
}
// Substring starting with i of length L
String temp = s.substring(i, i+l);
// Prefix function of the substring temp
int [] pref = prefix_function(temp);
// Checking if the substring is
// of the form of dp[i][k]^n
if (l % (l - pref[l - 1 ]) == 0 ) {
// If yes, check if dp[i][k] is
// less than dp[i][j]
dp[i][j] = Math.min(dp[i][j],
dp[i][i + (l - pref[l - 1 ] - 1 )]);
}
}
}
// Finally, print the required answer
System.out.println(dp[ 0 ][n - 1 ]);
}
// Driver Code
public static void main(String args[])
{
// Given Input
int n = 4 ;
String s = "aaba" ;
// Function Call
minLength(s, n);
}
} // This code is contributed by shinjanpatra |
# Python program for the above approach # Prefix function to calculate # longest prefix that is also # the suffix of the substring S def prefix_function(s):
n = len (s)
pi = [ 0 for i in range (n)]
for i in range ( 1 ,n):
j = pi[i - 1 ]
while (j > 0 and s[i] ! = s[j]):
j = pi[j - 1 ]
if (s[i] = = s[j]):
j + = 1
pi[i] = j
return pi
# Function to find the length of the # shortest compressed string def minLength(s,n):
# Declare a 2D dp vector
dp = [[ 10000 for col in range (n + 1 )] for row in range (n + 1 )]
# Traversing substring on the basis of length
for l in range ( 1 ,n + 1 ):
# For loop for each substring of length l
for i in range (n - l + 1 ):
# Second substring coordinate
j = i + l - 1
# If the length of the string is 1
# then dp[i][j] = 1
if (i = = j):
dp[i][j] = 1
continue
# Finding smallest dp[i][j] value
# by breaking it in two substrings
for k in range (i,j):
dp[i][j] = min (dp[i][j],dp[i][k] + dp[k + 1 ][j])
# Substring starting with i of length L
temp = s[i:i + l]
# Prefix function of the substring temp
pref = prefix_function(temp)
# Checking if the substring is
# of the form of dp[i][k]^n
if (l % (l - pref[l - 1 ]) = = 0 ):
# If yes, check if dp[i][k] is
# less than dp[i][j]
dp[i][j] = min (dp[i][j],dp[i][i + (l - pref[l - 1 ] - 1 )])
# Finally, print the required answer
print (dp[ 0 ][n - 1 ])
# Driver Code # Given Input n = 4
s = "aaba"
# Function Call minLength(s, n) # This code is contributed by shinjanpatra |
// C# program to implement above approach using System;
using System.Collections.Generic;
class GFG
{ // Prefix function to calculate
// longest prefix that is also
// the suffix of the substring S
static int [] prefix_function(String s)
{
int n = s.Length;
int [] pi = new int [n];
for ( int i = 1 ; i < n ; i++) {
int j = pi[i - 1];
while (j > 0 && s[i] != s[j]){
j = pi[j - 1];
}
if (s[i] == s[j]){
j++;
}
pi[i] = j;
}
return pi;
}
// Function to find the length of the
// shortest compressed string
static void minLength(String s, int n)
{
// Declare a 2D dp vector
int [][] dp = new int [n + 1][];
for ( int i = 0 ; i <= n ; i++){
dp[i] = new int [n+1];
}
foreach ( int [] row in dp){
for ( int i = 0 ; i < row.Length ; i++){
row[i] = 10000;
}
}
// Traversing substring on the basis of length
for ( int l = 1 ; l <= n ; l++) {
// For loop for each substring of length l
for ( int i = 0; i < n - l + 1; i++) {
// Second substring coordinate
int j = i + l - 1;
// If the length of the string is 1
// then dp[i][j] = 1
if (i == j) {
dp[i][j] = 1;
continue ;
}
// Finding smallest dp[i][j] value
// by breaking it in two substrings
for ( int k = i; k < j; k++) {
dp[i][j] = Math.Min(dp[i][j], dp[i][k] + dp[k + 1][j]);
}
// Substring starting with i of length L
String temp = s.Substring(i, l);
// Prefix function of the substring temp
int [] pref = prefix_function(temp);
// Checking if the substring is
// of the form of dp[i][k]^n
if (l % (l - pref[l - 1]) == 0) {
// If yes, check if dp[i][k] is
// less than dp[i][j]
dp[i][j] = Math.Min(dp[i][j], dp[i][i + (l - pref[l - 1] - 1)]);
}
}
}
// Finally, print the required answer
Console.Write(dp[0][n - 1]);
}
// Driver Code
public static void Main( string [] args){
int n = 4;
String s = "aaba" ;
// Function Call
minLength(s, n);
}
} // This code is contributed by subhamgoyal2014. |
<script> // JavaScript program for the above approach // Prefix function to calculate // longest prefix that is also // the suffix of the substring S function prefix_function(s)
{ let n = s.length;
let pi = new Array(n).fill(0);
for (let i = 1; i < n; i++)
{
let j = pi[i - 1];
while (j > 0 && s[i] != s[j])
j = pi[j - 1];
if (s[i] == s[j])
j++;
pi[i] = j;
}
return pi;
} // Function to find the length of the // shortest compressed string function minLength(s, n)
{ // Declare a 2D dp vector
let dp = new Array(n + 1).fill(10000).map(()=> new Array(n + 1).fill(10000));
// Traversing substring on the basis of length
for (let l = 1; l <= n; l++)
{
// For loop for each substring of length l
for (let i = 0; i < n - l + 1; i++)
{
// Second substring coordinate
let j = i + l - 1;
// If the length of the string is 1
// then dp[i][j] = 1
if (i == j) {
dp[i][j] = 1;
continue ;
}
// Finding smallest dp[i][j] value
// by breaking it in two substrings
for (let k = i; k < j; k++) {
dp[i][j] = Math.min(dp[i][j],dp[i][k] + dp[k + 1][j]);
}
// Substring starting with i of length L
let temp = s.substring(i, i+l);
// Prefix function of the substring temp
let pref = prefix_function(temp);
// Checking if the substring is
// of the form of dp[i][k]^n
if (l % (l - pref[l - 1]) == 0)
{
// If yes, check if dp[i][k] is
// less than dp[i][j]
dp[i][j] = Math.min(dp[i][j],
dp[i][i + (l - pref[l - 1] - 1)]);
}
}
}
// Finally, print the required answer
document.write(dp[0][n - 1], "</br>" );
} // Driver Code // Given Input let n = 4; let s = "aaba" ;
// Function Call minLength(s, n); // This code is contributed by shinjanpatra </script> |
3
Time Complexity: O(N^3)
Auxiliary Space: O(N^2)