Saturday, September 21, 2024
Google search engine
HomeData Modelling & AILongest Possible Chunked Palindrome

Longest Possible Chunked Palindrome

Given a string, the task is to return the length of its longest possible chunked palindrome. It means a palindrome formed by substring in the case when it is not formed by characters of the string. For a better understanding look at the example 

Examples:

Input : ghiabcdefhelloadamhelloabcdefghi 
Output : 7
(ghi)(abcdef)(hello)(adam)(hello)(abcdef)(ghi)

Input : merchant
Output : 1
(merchant)

Input : antaprezatepzapreanta
Output : 11
(a)(nt)(a)(pre)(za)(tpe)(za)(pre)(a)(nt)(a)

Input : neveropen
Output : 3
(neveropen)(for)(neveropen)

The entire idea is to create chunks from left and right and recursively. 

As you can see, we can match substring from the left side chunk and match it with the exact right side chunk. Once we get a match, we recursively count the length of the longest possible chunked palindrome in the remaining string. We end the recursion once no string is left or when no more valid chunked parts can be found. 

Implementation:

C++




// C++ program to find the length of longest palindromic chunk
#include <bits/stdc++.h>
using namespace std;
 
// Here curr_str is the string whose LCP is needed
// len is length of string evaluated till now
// and str is original string
int LPCRec(string curr_str, int count, int len, string str)
    {
        // if there is noting at all!!
        if (curr_str.size()==0)
            return (0);
 
        // if a single letter is left out
        if (curr_str.size() <= 1)
        {
            if (count != 0 && (str.size() - len )<= 1)
                return (count + 1);
            else
                return (1);
        }
 
        // for each length of substring chunk in string
        int n = curr_str.size();
        for (int i = 0; i < n/2; i++)
        {
            // if left side chunk and right side chunk
            // are same
            if (curr_str.substr(0, i+1) == curr_str.substr(n-1-i,i+1))
            {
                // Call LCP for the part between the
                // chunks and add 2 to the result.
                // Length of string evaluated till
                // now is increased by (i+1)*2
                return LPCRec(curr_str.substr(i+1, n-2-2*i), //
                        count + 2,
                        len + (i+1)*2, str);
            }
        }
 
        return count + 1;
    }
 
 
// Wrapper over LPCRec()
int LPC(string str)
{
    return LPCRec(str, 0, 0, str);
}
 
 
// driver function
int main()
{
    cout<<"V : "<<LPC("V")<<endl;
    cout<<"VOLVO : " << LPC("VOLVO")<<endl;
    cout<<"VOLVOV : " << LPC("VOLVOV")<<endl;
    cout<<"ghiabcdefhelloadamhelloabcdefghi : "<<
        LPC("ghiabcdefhelloadamhelloabcdefghi")<<endl;
         
    cout<<"ghiabcdefhelloadamhelloabcdefghik : "<<
                    LPC("ghiabcdefhelloadamhelloabcdefghik")<<endl;
 
    cout<<"antaprezatepzapreanta : " <<
                    LPC("antaprezatepzapreanta");
}
 
// This code is contributed by Pushpesh Raj


Java




/* Java program to find the length of longest palindromic
   chunk */
import java.util.*;
import java.lang.*;
import java.io.*;
 
class LongestPalindromicChunk
{
    // Here s is the string whose LCP is needed
    // ln is length of string evaluated till now
    // and str is original string
    private static int LPCRec(String curr_str, int count,
                             int len, String str)
    {
        // if there is noting at all!!
        if (curr_str == null || curr_str.isEmpty())
            return (0);
 
        // if a single letter is left out
        if (curr_str.length() <= 1)
        {
            if (count != 0 && str.length() - len <= 1)
                return (count + 1);
            else
                return (1);
        }
 
        // for each length of substring chunk in string
        int n = curr_str.length();
        for (int i = 0; i < n/2; i++)
        {
            // if left side chunk and right side chunk
            // are same
            if (curr_str.substring(0, i + 1).
                equals(curr_str.substring(n-1-i, n)))
            {
                // Call LCP for the part between the
                // chunks and add 2 to the result.
                // Length of string evaluated till
                // now is increased by (i+1)*2
                return LPCRec(curr_str.substring(i+1, n-1-i),
                           count + 2,
                           len + (i+1)*2, str);
            }
        }
 
        return count + 1;
    }
 
    // Wrapper over LPCRec()
    public static int LPC(String str)
    {
        return LPCRec(str, 0, 0, str);
    }
 
    // driver function
    public static void main(String[] args)
    {
        System.out.println("V : " + LPC("V"));
        System.out.println("VOLVO : " + LPC("VOLVO"));
        System.out.println("VOLVOV : " + LPC("VOLVOV"));
        System.out.println("ghiabcdefhelloadamhelloabcdefghi : " +
                        LPC("ghiabcdefhelloadamhelloabcdefghi"));
 
        System.out.println("ghiabcdefhelloadamhelloabcdefghik : " +
                        LPC("ghiabcdefhelloadamhelloabcdefghik"));
 
        System.out.println("antaprezatepzapreanta : " +
                        LPC("antaprezatepzapreanta"));
    }
}


Python3




# Python3 program to find length of
# longest palindromic chunk
 
# Here curr_str is the string whose
# LCP is needed leng is length of
# string evaluated till now and s 
# is original string
def LPCRec(curr_str, count, leng, s):
     
    # If there is nothing at all!!
    if not curr_str:
        return 0
 
    # If a single letter is left out
    if len(curr_str) <= 1:
        if count != 0 and len(s) - leng <= 1:
            return (count + 1)
        else:
            return 1
 
    # For each length of substring
    # chunk in string
    n = len(curr_str)
    for i in range(n // 2):
         
        # If left side chunk and right
        # side chunk are same
        if (curr_str[0 : i + 1] ==
            curr_str[n - 1 - i : n]):
             
            # Call LCP for the part between the
            # chunks and add 2 to the result.
            # Length of string evaluated till
            # now is increased by (i+1)*2
            return LPCRec(curr_str[i + 1 : n - 1 - i],
                          count + 2, leng + (i + 1) * 2, s)
                           
    return count + 1
 
# Wrapper over LPCRec()
def LPC(s):
     
    return LPCRec(s, 0, 0, s)
 
# Driver code
print("V :", LPC("V"))
print("VOLVO :", LPC("VOLVO"))
print("VOLVOV :", LPC("VOLVOV"))
print("ghiabcdefhelloadamhelloabcdefghi :",
  LPC("ghiabcdefhelloadamhelloabcdefghi"))
 
print("ghiabcdefhelloadamhelloabcdefghik :",
  LPC("ghiabcdefhelloadamhelloabcdefghik"))
 
print("antaprezatepzapreanta :",
  LPC("antaprezatepzapreanta"))
 
# This code is contributed by Prateek Gupta


C#




// C# program to find length of
// longest palindromic chunk
using System;
 
class GFG
{
// Here s is the string whose LCP
// is needed ln is length of string
// evaluated till now and str is
// original string
private static int LPCRec(string curr_str, int count,
                          int len, string str)
{
    // if there is noting at all!!
    if (string.ReferenceEquals(curr_str, null) ||
                               curr_str.Length == 0)
    {
        return (0);
    }
 
    // if a single letter is left out
    if (curr_str.Length <= 1)
    {
        if (count != 0 && str.Length - len <= 1)
        {
            return (count + 1);
        }
        else
        {
            return (1);
        }
    }
 
    // for each length of substring
    // chunk in string
    int n = curr_str.Length;
    for (int i = 0; i < n / 2; i++)
    {
        // if left side chunk and right side chunk
        // are same
        if (curr_str.Substring(0, i + 1).Equals(
            curr_str.Substring(n - 1 - i, n - (n - 1 - i))))
        {
            // Call LCP for the part between the
            // chunks and add 2 to the result.
            // Length of string evaluated till
            // now is increased by (i+1)*2
            return LPCRec(curr_str.Substring(i + 1, (n - 1 - i) -
                         (i + 1)), count + 2, len + (i + 1) * 2, str);
        }
    }
 
    return count + 1;
}
 
// Wrapper over LPCRec()
public static int LPC(string str)
{
    return LPCRec(str, 0, 0, str);
}
 
// Driver Code
public static void Main(string[] args)
{
    Console.WriteLine("V : " + LPC("V"));
    Console.WriteLine("VOLVO : " + LPC("VOLVO"));
    Console.WriteLine("VOLVOV : " + LPC("VOLVOV"));
    Console.WriteLine("ghiabcdefhelloadamhelloabcdefghi : " +
                    LPC("ghiabcdefhelloadamhelloabcdefghi"));
 
    Console.WriteLine("ghiabcdefhelloadamhelloabcdefghik : " +
                    LPC("ghiabcdefhelloadamhelloabcdefghik"));
 
    Console.WriteLine("antaprezatepzapreanta : " +
                    LPC("antaprezatepzapreanta"));
}
}
 
// This code is contributed by Shrikant13


Javascript




<script>
 
// JavaScript program to find length of
// longest palindromic chunk
 
// Here curr_str is the string whose
// LCP is needed leng is length of
// string evaluated till now and s 
// is original string
function LPCRec(curr_str, count, leng, s){
     
    // If there is nothing at all!!
    if(!curr_str)
        return 0
 
    // If a single letter is left out
    if(curr_str.length <= 1){
        if (count != 0 && s.length - leng <= 1)
            return (count + 1)
        else
            return 1
    }
 
    // For each length of substring
    // chunk in string
    let n = curr_str.length
    for(let i=0;i<Math.floor(n/2);i++){
         
        // If left side chunk and right
        // side chunk are same
        if (curr_str.substring(0,i+1) == curr_str.substring(n-1-i,n))
             
            // Call LCP for the part between the
            // chunks and add 2 to the result.
            // Length of string evaluated till
            // now is increased by (i+1)*2
            return LPCRec(curr_str.substring(i + 1,n - 1 - i), count + 2, leng + (i + 1) * 2, s)
    }
                           
    return count + 1
}
 
// Wrapper over LPCRec()
function LPC(s){
     
    return LPCRec(s, 0, 0, s)
}
 
// Driver code
document.write("V :", LPC("V"),"</br>")
document.write("VOLVO :", LPC("VOLVO"),"</br>")
document.write("VOLVOV :", LPC("VOLVOV"),"</br>")
document.write("ghiabcdefhelloadamhelloabcdefghi :",
  LPC("ghiabcdefhelloadamhelloabcdefghi"),"</br>")
 
document.write("ghiabcdefhelloadamhelloabcdefghik :",
  LPC("ghiabcdefhelloadamhelloabcdefghik"),"</br>")
 
document.write("antaprezatepzapreanta :",
  LPC("antaprezatepzapreanta"),"</br>")
 
// This code is contributed by shinjanpatra
 
</script>


Output

V : 1
VOLVO : 3
VOLVOV : 5
ghiabcdefhelloadamhelloabcdefghi : 7
ghiabcdefhelloadamhelloabcdefghik : 1
antaprezatepzapreanta : 11

Following is the C++ implementation with memoization for above problem. 

Implementation:

CPP




#include <climits>
#include <iostream>
#include <unordered_map>
using namespace std;
 
unordered_map<string, int> mem;
 
int process(string& s, int l, int r)
{
    int ans = 1;
    if (l > r)
        return 0;
    // check if we've already solved this
    if (mem.find(s.substr(l, r - l + 1)) != mem.end())
        return mem[s.substr(l, r - l + 1)];
    for (int len = 1; len <= (r - l + 1) / 2; len++) {
        if (s.substr(l, len) == s.substr(r - len + 1, len))
            ans = max(ans,
                      2 + process(s, l + len, r - len));
    }
    // remember result for future
    mem[s.substr(l, r - l + 1)] = ans;
    return ans;
}
 
int LPC(string s) { return process(s, 0, s.length() - 1); }
 
int main()
{
    cout << LPC("aaaaabaababbaabaaababababababababbbbaaaaa")
         << endl;
    return 0;
}


Java




import java.util.HashMap;
 
public class Main {
 
  static HashMap<String, Integer> mem = new HashMap<>();
 
  public static int process(String s, int l, int r) {
    int ans = 1;
    if (l > r) {
      return 0;
    }
     
    // check if we've already solved this
    if (mem.containsKey(s.substring(l, r + 1))) {
      return mem.get(s.substring(l, r + 1));
    }
    for (int len = 1; len <= (r - l + 1) / 2; len++) {
      if (s.substring(l, l + len).equals(s.substring(r - len + 1, r + 1))) {
        ans = Math.max(ans, 2 + process(s, l + len, r - len));
      }
    }
    // remember result for future
    mem.put(s.substring(l, r + 1), ans);
    return ans;
  }
 
  public static int LPC(String s) {
    return process(s, 0, s.length() - 1);
  }
 
  public static void main(String[] args) {
    System.out.println(LPC("aaaaabaababbaabaaababababababababbbbaaaaa"));
  }
}
 
// This code is contributed by Aman Kumar


Python3




# Python code for the approach
 
mem = {}
 
def process(s,l,r):
    global mem
    ans = 1
    if (l > r):
        return 0
    # check if we've already solved this
    if (s[l: r+1] in mem):
        return mem[s[l: r+1]]
    for Len in range(1,(r-l+1)//2 + 1,1):
        if (s[l: Len+l] == s[r-Len+1:r+1]):
            ans = max(ans, 2 + process(s, l+Len, r-Len))
    # remember result for future
    mem[s[l: r+1]] = ans
    return ans
 
def LPC(s):
    return process(s, 0, len(s)-1)
 
# driver code
 
print(LPC("aaaaabaababbaabaaababababababababbbbaaaaa"))
 
# This code is contributed by shinjanpatra.


Javascript




let mem = {};
 
function process(s, l, r) {
    let ans = 1;
    if (l > r) {
        return 0;
    }
     
    // check if we've already solved this
    if (s.slice(l, r + 1) in mem) {
        return mem[s.slice(l, r + 1)];
    }
    for (let Len = 1; Len <= Math.floor((r - l + 1) / 2); Len++) {
        if (s.slice(l, Len + l) === s.slice(r - Len + 1, r + 1)) {
            ans = Math.max(ans, 2 + process(s, l + Len, r - Len));
        }
    }
     
    // remember result for future
    mem[s.slice(l, r + 1)] = ans;
    return ans;
}
 
function LPC(s) {
    return process(s, 0, s.length - 1);
}
 
// driver code
console.log(LPC("aaaaabaababbaabaaababababababababbbbaaaaa"));
 
// This code is contributed by adityashatmfh


C#




// C# program for the above approach
 
using System;
using System.Collections.Generic;
 
class Program
{
    static Dictionary<string, int> mem = new Dictionary<string, int>();
 
    static int Process(string s, int l, int r)
    {
        int ans = 1;
        if (l > r)
            return 0;
        // check if we've already solved this
        if (mem.ContainsKey(s.Substring(l, r - l + 1)))
            return mem[s.Substring(l, r - l + 1)];
        for (int len = 1; len <= (r - l + 1) / 2; len++)
        {
            if (s.Substring(l, len) == s.Substring(r - len + 1, len))
                ans = Math.Max(ans, 2 + Process(s, l + len, r - len));
        }
        // remember result for future
        mem[s.Substring(l, r - l + 1)] = ans;
        return ans;
    }
 
    static int LPC(string s)
    {
        return Process(s, 0, s.Length - 1);
    }
 
    static void Main(string[] args)
    {
        Console.WriteLine(LPC("aaaaabaababbaabaaababababababababbbbaaaaa"));
    }
}
 
 
// This code is contributed by prince


Output

13

Time Complexity: O(N^3), where N is the length of the input string.

Auxiliary Space: O(N^2)

This article is contributed by Aditya Nihal Kumar Singh. If you like neveropen and would like to contribute, you can also write an article using write.geeksforgeeks.org or mail your article to review-team@geeksforgeeks.org. See your article appearing on the neveropen main page and help other Geeks.

Feeling lost in the world of random DSA topics, wasting time without progress? It’s time for a change! Join our DSA course, where we’ll guide you on an exciting journey to master DSA efficiently and on schedule.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!

RELATED ARTICLES

Most Popular

Recent Comments