Skip to content
Related Articles

Related Articles

Improve Article

Count of palindromes that can be obtained by concatenating equal length prefix and substrings

  • Last Updated : 27 Apr, 2021
Geek Week

Prerequisites: Z-algorithm

Given a string S, the task is to find the maximum number of palindromes that can be formed after performing the given steps:

  1. Choose a non-empty prefix P and a non-empty substring T of equal length.
  2. Reverse either P or T and concatenate them.

Note: P and T can be overlapping.

Examples:

Input: S = “abab”
Output: 6
Explanation: 
Consider prefix as S[0 : 1] (= “ab“) and reverse the substring S[2 : 3]. Resultant string after concatenating prefix with reversed substring is “abba”, which is a palindrome.
All possible prefixes are [“a”, “ab”, ”aba”, ”abab”]
All possible suffixes are [“a”, ”b”, ”a”, ”b”, ”ab”, ”ba”, ”ab”, ”aba”, ”bab”, ”abab”].
Therefore, all possible palindromes are [“aa”, ”aa”, ”abba”, ”abba”, ”abaaba”, ”ababbaba”].



Input: S = “abcd”
Output: 4

 

Naive Approach: Generate all possible prefixes and all possible substrings. Concatenate all equal length prefix and substring(after reversing) pairs and check if the string obtained is palindrome or not

Time Complexity: O(N3)
Auxiliary Space: O(N2)

Efficient Approach: The above approach can be optimized based on the observation that the length of the concatenated strings will always be even. Therefore, only those strings need to be considered in which the first half is the mirror image of the second half. Therefore, the problem reduces to counting substrings for every possible prefix which are equal to that prefix, which can be done using Z-function.

The z-function over a string will return an array Z[] where Z[i] represents the length of the longest prefix that same as the sub-string starting at position i and ending at position i+Z[i]. Hence, the count will be \sum Z[i]+1              .

Follow the steps below to solve the problem:

  1. The idea is to maintain an interval [l, r] which is the interval with max r such that [l, r] is a prefix substring (substring which is also prefix).
  2. If i ≤ r, then Z[i] is equal to minimum of r – i + 1 and Z[i – 1].
  3. Now, increment Z[i] until i + Z[i] is less than N and character at index Z[i] and i + Z[i] are equal in the given string.
  4. Now, if i + Z[i] – 1 > r, then set l to i and r to i + Z[i] – 1.
  5. Repeat the above steps for i from 0 to N-1.
  6. The answer is the sum of Z[i] + 1 for each i (0 ≤ i ≤ N-1).

Below is the implementation of the above approach:

C++14




// C++ program the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to calculate the
// number of palindromes
int countPalindromes(string S)
{
    int N = (int)S.length();
    vector<int> Z(N);
 
    // Calculation of Z-array
    int l = 0, r = 0;
    for (int i = 1; i < N; i++) {
 
        if (i <= r)
            Z[i] = min(r - i + 1, Z[i - l]);
 
        while (i + Z[i] < N
               && S[Z[i]] == S[i + Z[i]]) {
            Z[i]++;
        }
 
        if (i + Z[i] - 1 > r) {
 
            l = i;
            r = i + Z[i] - 1;
        }
    }
 
    // Calculation of sigma(Z[i]+1)
    int sum = 0;
    for (int i = 0; i < Z.size(); i++) {
        sum += Z[i] + 1;
    }
 
    // Return the count
    return sum;
}
 
// Driver Code
int main()
{
    // Given String
    string S = "abab";
    cout << countPalindromes(S);
 
    return 0;
}

Java




// Java program for the above approach 
import java.util.*;
 
class GFG{
     
// Function to calculate the
// number of palindromes
static int countPalindromes(String S)
{
    int N = (int)S.length();
    int[] Z = new int[(N)];
     
    // Calculation of Z-array
    int l = 0, r = 0;
     
    for(int i = 1; i < N; i++)
    {
        if (i <= r)
            Z[i] = Math.min(r - i + 1,
                              Z[i - l]);
 
        while (i + Z[i] < N &&
               S.charAt(Z[i]) ==
               S.charAt(i + Z[i]))
        {
            Z[i]++;
        }
 
        if (i + Z[i] - 1 > r)
        {
            l = i;
            r = i + Z[i] - 1;
        }
    }
 
    // Calculation of sigma(Z[i]+1)
    int sum = 0;
     
    for(int i = 0; i < Z.length; i++)
    {
        sum += Z[i] + 1;
    }
     
    // Return the count
    return sum;
}
 
// Driver Code   
public static void main (String[] args)   
     
    // Given String
    String S = "abab";
     
    System.out.println(countPalindromes(S));
}
}
 
// This code is contributed by code_hunt

Python3




# Python3 program the above approach
 
# Function to calculate the
# number of palindromes
def countPalindrome(S):
    N = len(S)
    Z = [0] * N
     
    # Calculation of Z-array
    l = 0
    r = 0
    for i in range(1, N):
        if i <= r:
            Z[i] = min(r - i + 1, Z[i - 1])
        while((i + Z[i]) < N and (S[Z[i]] == S[i + Z[i]])):
            Z[i] += 1
        if ((i + Z[i] - 1) > r):
            l = ir = i + Z[i] - 1
             
    # Calculation of sigma(Z[i]+1)
    sum = 0
    for i in range(0, len(Z)):
        sum += Z[i] + 1
     
    # return the count
    return sum
 
# Driver code
 
# Given String
S = "abab"
print(countPalindrome(S))
 
# This code is contributed by virusbuddah

C#




// C# program for the above approach 
using System;
 
public class GFG{
     
// Function to calculate the
// number of palindromes
static int countPalindromes(String S)
{
    int N = (int)S.Length;
    int[] Z = new int[(N)];
     
    // Calculation of Z-array
    int l = 0, r = 0;
     
    for(int i = 1; i < N; i++)
    {
        if (i <= r)
            Z[i] = Math.Min(r - i + 1,
                              Z[i - l]);
        while (i + Z[i] < N &&
               S[Z[i]] ==
               S[i + Z[i]])
        {
            Z[i]++;
        }
 
        if (i + Z[i] - 1 > r)
        {
            l = i;
            r = i + Z[i] - 1;
        }
    }
 
    // Calculation of sigma(Z[i]+1)
    int sum = 0;
     
    for(int i = 0; i < Z.Length; i++)
    {
        sum += Z[i] + 1;
    }
     
    // Return the count
    return sum;
}
 
// Driver Code   
public static void Main(String[] args)   
     
    // Given String
    String S = "abab";
     
    Console.WriteLine(countPalindromes(S));
}
}
 
// This code is contributed by 29AjayKumar

Javascript




<script>
// Javascript program the above approach
 
// Function to calculate the
// number of palindromes
function countPalindromes(S)
{
    var N = S.length;
    var Z = Array(N).fill(0);
 
    // Calculation of Z-array
    var l = 0, r = 0;
    for (var i = 1; i < N; i++) {
 
        if (i <= r)
            Z[i] = Math.min(r - i + 1, Z[i - l]);
 
        while (i + Z[i] < N
            && S[Z[i]] == S[i + Z[i]]) {
            Z[i]++;
        }
 
        if (i + Z[i] - 1 > r) {
 
            l = i;
            r = i + Z[i] - 1;
        }
    }
 
    // Calculation of sigma(Z[i]+1)
    var sum = 0;
    for (var i = 0; i < Z.length; i++) {
        sum += Z[i] + 1;
    }
 
    // Return the count
    return sum;
}
 
// Driver Code
// Given String
var S = "abab";
document.write( countPalindromes(S));
 
</script>
Output: 
6

 

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

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up
Recommended Articles
Page :