Given a string S and a positive integer K, The task is to maximize the product of the length of non-overlapping palindromic substrings each of length at least K from the string S.
Examples:
Input: S = “abaccdbbd”, K = 3 Output: 12 Explanation: Select the substrings underlined in s = “abaccdbbd“, which is of length 3 and 4. The product of these results is 12, which is the most optimal answer.
Input: S = “adbcda”, K = 2 Output: 0 Explanation: There is no palindrome of length at least 2.
Precalculate all the palindromic substrings. Every index has two options either our valid palindrome will start from here which we include in our optimal result or we exclude the current index. Finally, maximize the result obtained it.
Follow the steps below to implement the above idea:
- Declare a 2D dp[] array to store if the substring from any i to any j is a palindrome or not.
- Initialize a dp2 array with -1, where dp2[i] will store the maximum result possible till index i.
- Precalculate to find all the substrings which are palindrome.
- Call a recursive function [say maxProduct()] and do the following:
- If current index i equal n (length of the given string), return 1.
- Check if the calculation for ith index is already done in the dp2[] array, if done then return the stored value from it.
- Find the valid substring which is a palindrome string starting from the current index.
- Recursively call for another palindromic substring after the ending of the first valid substring.
- Recursively call for the condition when ith character is not considered to be the starting position of a valid palindromic substring.
- Store calculation for the ith index into the dp2[] array
- Return the maximum value returned from the recursive function as the required result.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maxProduct( int i, string& s, int k,
vector<vector< bool > >& dp,
vector< int >& dp2)
{
if (i == s.size())
return 1;
if (dp2[i] != -1)
return dp2[i];
int result = 0;
for ( int j = i; j < s.size(); j++) {
if (dp[i][j] && j - i + 1 >= k) {
result = max(result,
(j - i + 1)
* maxProduct(j + 1, s, k, dp, dp2));
}
}
result = max(result, maxProduct(i + 1, s, k, dp, dp2));
return dp2[i] = result;
}
int maxPalindromes(string s, int k)
{
int n = s.size();
vector<vector< bool > > dp(n + 1,
vector< bool >(n + 1, false ));
vector< int > dp2(n + 1, -1);
for ( int i = 0; i < n; i++) {
dp[i][i] = true ;
}
for ( int i = 0; i < n - 1; i++) {
if (s[i] == s[i + 1]) {
dp[i][i + 1] = true ;
}
}
for ( int len = 3; len < n; len++) {
int i = 0, j = len - 1;
while (j < n) {
if (s[i] == s[j]) {
if (dp[i + 1][j - 1])
dp[i][j] = true ;
}
i++;
j++;
}
}
int ans = maxProduct(0, s, k, dp, dp2);
if (ans == 1 and k > 1)
return 0;
return ans;
}
int main()
{
string S = "abaccdbbd" ;
int K = 3;
cout << maxPalindromes(S, K) << endl;
S = "adbcda" ;
K = 2;
cout << maxPalindromes(S, K) << endl;
S = "ab" ;
K = 1;
cout << maxPalindromes(S, K) << endl;
return 0;
}
|
Java
import java.io.*;
import java.util.*;
class GFG {
static int maxProduct( int i, String s, int k,
boolean [][] dp, int [] dp2)
{
if (i == s.length()) {
return 1 ;
}
if (dp2[i] != - 1 ) {
return dp2[i];
}
int result = 0 ;
for ( int j = i; j < s.length(); j++) {
if (dp[i][j] && j - i + 1 >= k) {
result = Math.max(
result,
(j - i + 1 )
* maxProduct(j + 1 , s, k, dp, dp2));
}
}
result = Math.max(result,
maxProduct(i + 1 , s, k, dp, dp2));
return dp2[i] = result;
}
static int maxPalindromes(String s, int k)
{
int n = s.length();
boolean [][] dp = new boolean [n + 1 ][n + 1 ];
int [] dp2 = new int [n + 1 ];
Arrays.fill(dp2, - 1 );
for ( int i = 0 ; i < n; i++) {
dp[i][i] = true ;
}
for ( int i = 0 ; i < n - 1 ; i++) {
if (s.charAt(i) == s.charAt(i + 1 )) {
dp[i][i + 1 ] = true ;
}
}
for ( int len = 3 ; len < n; len++) {
int i = 0 , j = len - 1 ;
while (j < n) {
if (s.charAt(i) == s.charAt(j)) {
if (dp[i + 1 ][j - 1 ])
dp[i][j] = true ;
}
i++;
j++;
}
}
int ans = maxProduct( 0 , s, k, dp, dp2);
if (ans == 1 && k > 1 )
return 0 ;
return ans;
}
public static void main(String[] args)
{
String S = "abaccdbbd" ;
int K = 3 ;
System.out.println(maxPalindromes(S, K));
S = "adbcda" ;
K = 2 ;
System.out.println(maxPalindromes(S, K));
S = "ab" ;
K = 1 ;
System.out.println(maxPalindromes(S, K));
}
}
|
Python3
def maxProduct(i, s, k, dp, dp2):
if (i = = len (s)):
return 1
if (dp2[i] ! = - 1 ):
return dp2[i]
result = 0
for j in range (i, len (s)):
if (dp[i][j] and j - i + 1 > = k):
result = max (result,
(j - i + 1 )
* maxProduct(j + 1 , s, k, dp, dp2))
result = max (result, maxProduct(i + 1 , s, k, dp, dp2))
dp2[i] = result
return dp2[i]
def maxPalindromes(s, k):
n = len (s)
dp = [[ False for _ in range (n + 1 )] for _ in range (n + 1 )]
dp2 = [ - 1 for _ in range (n + 1 )]
for i in range ( 0 , n):
dp[i][i] = True
for i in range ( 0 , n - 1 ):
if (s[i] = = s[i + 1 ]):
dp[i][i + 1 ] = True
for le in range ( 3 , n):
i = 0
j = le - 1
while (j < n):
if (s[i] = = s[j]):
if (dp[i + 1 ][j - 1 ]):
dp[i][j] = True
i + = 1
j + = 1
ans = maxProduct( 0 , s, k, dp, dp2)
if (ans = = 1 and k > 1 ):
return 0
return ans
if __name__ = = "__main__" :
S = "abaccdbbd"
K = 3
print (maxPalindromes(S, K))
S = "adbcda"
K = 2
print (maxPalindromes(S, K))
S = "ab"
K = 1
print (maxPalindromes(S, K))
|
C#
using System;
using System.Collections;
public class GFG {
static int maxProduct( int i, String s, int k,
bool [, ] dp, int [] dp2)
{
if (i == s.Length) {
return 1;
}
if (dp2[i] != -1) {
return dp2[i];
}
int result = 0;
for ( int j = i; j < s.Length; j++) {
if (dp[i, j] && j - i + 1 >= k) {
result = Math.Max(
result,
(j - i + 1)
* maxProduct(j + 1, s, k, dp, dp2));
}
}
result = Math.Max(result,
maxProduct(i + 1, s, k, dp, dp2));
return dp2[i] = result;
}
static int maxPalindromes(String s, int k)
{
int n = s.Length;
bool [, ] dp = new bool [n + 1, n + 1];
int [] dp2 = new int [n + 1];
Array.Fill(dp2, -1);
for ( int i = 0; i < n; i++) {
dp[i, i] = true ;
}
for ( int i = 0; i < n - 1; i++) {
if (s[i] == s[i + 1]) {
dp[i, i + 1] = true ;
}
}
for ( int len = 3; len < n; len++) {
int i = 0, j = len - 1;
while (j < n) {
if (s[i] == s[j]) {
if (dp[i + 1, j - 1])
dp[i, j] = true ;
}
i++;
j++;
}
}
int ans = maxProduct(0, s, k, dp, dp2);
if (ans == 1 && k > 1)
return 0;
return ans;
}
static public void Main()
{
string S = "abaccdbbd" ;
int K = 3;
Console.WriteLine(maxPalindromes(S, K));
S = "adbcda" ;
K = 2;
Console.WriteLine(maxPalindromes(S, K));
S = "ab" ;
K = 1;
Console.WriteLine(maxPalindromes(S, K));
}
}
|
Javascript
function maxProduct(i, s, k, dp, dp2)
{
if (i === s.length) {
return 1;
}
if (dp2[i] !== -1) {
return dp2[i];
}
let result = 0;
for (let j = i; j < s.length; j++)
{
if (dp[i][j] && j - i + 1 >= k)
{
result = Math.max(result, (j - i + 1) *
maxProduct(j + 1, s, k, dp, dp2));
}
}
result = Math.max(result, maxProduct(i + 1, s, k, dp, dp2));
return dp2[i] = result;
}
function maxPalindromes(s, k) {
const n = s.length;
const dp = new Array(n + 1);
for (let i = 0; i < n + 1; i++) {
dp[i] = new Array(n + 1);
}
const dp2 = new Array(n + 1).fill(-1);
for (let i = 0; i < n; i++) {
dp[i][i] = true ;
}
for (let i = 0; i < n - 1; i++) {
if (s[i] === s[i + 1]) {
dp[i][i + 1] = true ;
}
}
for (let len = 3; len < n; len++) {
let i = 0, j = len - 1;
while (j < n) {
if (s[i] === s[j]) {
if (dp[i + 1][j - 1]) {
dp[i][j] = true ;
}
}
i++;
j++;
}
}
const ans = maxProduct(0, s, k, dp, dp2);
if (ans === 1 && k > 1){
return 0;
}
return ans;
}
let S = "abaccdbbd" ;
let K = 3;
console.log(maxPalindromes(S, K) + "<br>" );
S = "adbcda" ;
K = 2;
console.log(maxPalindromes(S, K) + "<br>" );
S = "ab" ;
K = 1;
console.log(maxPalindromes(S, K));
|
Time Complexity: O(N2) Auxiliary Space: O(N2)
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
int maxPalindromes(string s, int k)
{
int n = s.size();
vector<vector< bool > > dp(n, vector< bool >(n, false ));
for ( int i = 0; i < n; i++) {
dp[i][i] = true ;
if (i < n - 1 && s[i] == s[i + 1]) {
dp[i][i + 1] = true ;
}
}
for ( int len = 3; len <= n; len++) {
for ( int i = 0; i < n - len + 1; i++) {
int j = i + len - 1;
if (s[i] == s[j]) {
dp[i][j] = dp[i + 1][j - 1];
}
}
}
vector< int > dp2(n, -1);
dp2[n - 1] = 1;
for ( int i = n - 2; i >= 0; i--) {
dp2[i] = dp2[i + 1];
for ( int j = i; j < n; j++) {
if (dp[i][j] && (j - i + 1) >= k) {
int temp = (j - i + 1);
if (j + 1 < n) {
temp *= dp2[j + 1];
}
dp2[i] = max(dp2[i], temp);
}
}
}
if (dp2[0] == 1 && k > 1) {
return 0;
}
return dp2[0];
}
int main()
{
string S = "abaccdbbd" ;
int K = 3;
cout << maxPalindromes(S, K) << endl;
S = "adbcda" ;
K = 2;
cout << maxPalindromes(S, K) << endl;
S = "ab" ;
K = 1;
cout << maxPalindromes(S, K) << endl;
return 0;
}
|
Java
import java.util.Arrays;
class Main {
static int maxPalindromes(String s, int k)
{
int n = s.length();
boolean [][] dp = new boolean [n][n];
for ( int i = 0 ; i < n; i++) {
dp[i][i] = true ;
if (i < n - 1
&& s.charAt(i) == s.charAt(i + 1 )) {
dp[i][i + 1 ] = true ;
}
}
for ( int len = 3 ; len <= n; len++) {
for ( int i = 0 ; i < n - len + 1 ; i++) {
int j = i + len - 1 ;
if (s.charAt(i) == s.charAt(j)) {
dp[i][j] = dp[i + 1 ][j - 1 ];
}
}
}
int [] dp2 = new int [n];
Arrays.fill(dp2, - 1 );
dp2[n - 1 ] = 1 ;
for ( int i = n - 2 ; i >= 0 ; i--) {
dp2[i] = dp2[i + 1 ];
for ( int j = i; j < n; j++) {
if (dp[i][j] && (j - i + 1 ) >= k) {
int temp = (j - i + 1 );
if (j + 1 < n) {
temp *= dp2[j + 1 ];
}
dp2[i] = Math.max(dp2[i], temp);
}
}
}
if (dp2[ 0 ] == 1 && k > 1 ) {
return 0 ;
}
return dp2[ 0 ];
}
public static void main(String[] args)
{
String S = "abaccdbbd" ;
int K = 3 ;
System.out.println(maxPalindromes(S, K));
S = "adbcda" ;
K = 2 ;
System.out.println(maxPalindromes(S, K));
S = "ab" ;
K = 1 ;
System.out.println(maxPalindromes(S, K));
}
}
|
Python3
def maxPalindromes(s, k):
n = len (s)
dp = [[ False ] * n for _ in range (n)]
for i in range (n):
dp[i][i] = True
if i < n - 1 and s[i] = = s[i + 1 ]:
dp[i][i + 1 ] = True
for length in range ( 3 , n + 1 ):
for i in range (n - length + 1 ):
j = i + length - 1
if s[i] = = s[j]:
dp[i][j] = dp[i + 1 ][j - 1 ]
dp2 = [ - 1 ] * n
dp2[n - 1 ] = 1
for i in range (n - 2 , - 1 , - 1 ):
dp2[i] = dp2[i + 1 ]
for j in range (i, n):
if dp[i][j] and (j - i + 1 ) > = k:
temp = (j - i + 1 )
if j + 1 < n:
temp * = dp2[j + 1 ]
dp2[i] = max (dp2[i], temp)
if dp2[ 0 ] = = 1 and k > 1 :
return 0
return dp2[ 0 ]
S = "abaccdbbd"
K = 3
print (maxPalindromes(S, K))
S = "adbcda"
K = 2
print (maxPalindromes(S, K))
S = "ab"
K = 1
print (maxPalindromes(S, K))
|
C#
using System;
using System.Collections.Generic;
class GFG
{
static int MaxPalindromes( string s, int k)
{
int n = s.Length;
bool [,] dp = new bool [n, n];
for ( int i = 0; i < n; i++)
{
dp[i, i] = true ;
if (i < n - 1 && s[i] == s[i + 1])
{
dp[i, i + 1] = true ;
}
}
for ( int len = 3; len <= n; len++)
{
for ( int i = 0; i < n - len + 1; i++)
{
int j = i + len - 1;
if (s[i] == s[j])
{
dp[i, j] = dp[i + 1, j - 1];
}
}
}
int [] dp2 = new int [n];
dp2[n - 1] = 1;
for ( int i = n - 2; i >= 0; i--)
{
dp2[i] = dp2[i + 1];
for ( int j = i; j < n; j++)
{
if (dp[i, j] && (j - i + 1) >= k)
{
int temp = (j - i + 1);
if (j + 1 < n)
{
temp *= dp2[j + 1];
}
dp2[i] = Math.Max(dp2[i], temp);
}
}
}
if (dp2[0] == 1 && k > 1)
{
return 0;
}
return dp2[0];
}
static void Main( string [] args)
{
string S = "abaccdbbd" ;
int K = 3;
Console.WriteLine(MaxPalindromes(S, K));
S = "adbcda" ;
K = 2;
Console.WriteLine(MaxPalindromes(S, K));
S = "ab" ;
K = 1;
Console.WriteLine(MaxPalindromes(S, K));
}
}
|
Javascript
const maxPalindromes = (s, k) => {
const n = s.length;
const dp = Array.from({ length: n }, () => Array(n).fill( false ));
for (let i = 0; i < n; i++) {
dp[i][i] = true ;
if (i < n - 1 && s[i] === s[i + 1]) {
dp[i][i + 1] = true ;
}
}
for (let length = 3; length <= n; length++) {
for (let i = 0; i < n - length + 1; i++) {
const j = i + length - 1;
if (s[i] === s[j]) {
dp[i][j] = dp[i + 1][j - 1];
}
}
}
const dp2 = Array(n).fill(-1);
dp2[n - 1] = 1;
for (let i = n - 2; i >= 0; i--) {
dp2[i] = dp2[i + 1];
for (let j = i; j < n; j++) {
if (dp[i][j] && (j - i + 1) >= k) {
let temp = j - i + 1;
if (j + 1 < n) {
temp *= dp2[j + 1];
}
dp2[i] = Math.max(dp2[i], temp);
}
}
}
if (dp2[0] === 1 && k > 1) {
return 0;
}
return dp2[0];
};
let S = "abaccdbbd" ;
let K = 3;
console.log(maxPalindromes(S, K));
S = "adbcda" ;
K = 2;
console.log(maxPalindromes(S, K));
S = "ab" ;
K = 1;
console.log(maxPalindromes(S, K));
|
Time Complexity: O(N^2) Auxiliary Space: O(N^2)
Related Articles:
|