Count palindromic characteristics of a String

Given a string s of length n, count the number of substrings having different types of palindromic characteristics.
Palindromic Characteristic is the number of k-palindromes in a string where k lies in range [0, n).
A string is 1-palindrome(or simply palindrome) if and only if it reads same the backward as it reads forward.
A string is k-palindrome (k > 1) if and only if :
1. Its left half is equal to its right half.
2. Its left half and right half should be non-empty (k – 1)-palindrome. The left half of a string of length ‘t’ is its prefix of length ⌊t/2⌋, and right half is the suffix of the same length.
Note : Each substring is counted as many times as it appears in the string. For example, in the string “aaa” the substring “a” appears 3 times.

Examples :

Input : abba
Output : 6 1 0 0
Explanation : 
"6" 1-palindromes = "a", "b", "b", "a", "bb", "abba".
"1" 2-palindrome = "bb". Because "b" is 1-palindrome 
and "bb" has both left and right parts equal. 
"0" 3-palindrome and 4-palindrome.

Input : abacaba
Output : 12 4 1 0 0 0 0
Explanation : 
"12" 1-palindromes = "a", "b", "a", "c", "a", "b", 
"a", "aba", "aca", "aba", "bacab", "abacaba".
"4" 2-palindromes = "aba", "aca", "aba", "abacaba". 
Because "a" and "aba" are 1-palindromes.
NOTE :  "bacab" is not 2-palindrome as "ba" 
is not 1-palindrome. "1" 3-palindrome = "abacaba". 
Because is "aba" is 2-palindrome. "0" other 
k-pallindromes where 4 < = k < = 7.

Approach : Take a string s and say it is a 1-palindrome and checking its left half also turns out to be a 1-palindrome then, obviously its right part will always be equal to left part (as the string is also a 1-palindrome) making the original string to be 2-palindrome. Now, similarly, checking the left half of the string, it also turns out to be a 1-palindrome then it will make left half to be 2-palindrome and hence, making original string to be 3-palindrome and so on checking it till only 1 alphabet is left or the part is not a 1-palindrome.
Lets take string = “abacaba”. As known “abacaba” is 1-palindrome. So, when checking for its left half “aba”, which is also a 1-palindrome, it makes “abacaba” a 2-palindrome. Then, check for “aba”‘s left half “a” which is also a 1-palindrome. So it makes “aba” a 2-palindrome and “aba” makes “abacaba” a 3-palindrome. So in other words, if a string is a k-palindrome then it is also a (k-1)-palindrome, (k-2)-palindrome and so on till 1-palindrome. Code for the same is given below which firsts check each and every substring if it is a palindrome or not and then counts the number of k-palindromic substrings recursively in logarithmic time.

Below is the implementation of above approach :

C++

// A C++ program which counts different
// palindromic characteristics of a string.
#include <bits/stdc++.h>
using namespace std;

const int MAX_STR_LEN = 1000;

bool P[MAX_STR_LEN][MAX_STR_LEN];
int Kpal[MAX_STR_LEN];

// A C++ function which checks whether a
// substring str[i..j] of a given string
// is a palindrome or not.
void checkSubStrPal(string str, int n)
{

    // P[i][j] = true if substring str
    // [i..j] is palindrome, else false
    memset(P, false, sizeof(P));

    // palindrome of single length
    for (int i = 0; i < n; i++)
        P[i][i] = true;

    // palindrome of length 2
    for (int i = 0; i < n - 1; i++)
        if (str[i] == str[i + 1])
            P[i][i + 1] = true;

    // Palindromes of length more then 2.
    // This loop is similar to Matrix Chain
    // Multiplication. We start with a gap of
    // length 2 and fill P table in a way that
    // gap between starting and ending indexes
    // increases one by one by outer loop.
    for (int gap = 2; gap < n; gap++)
    {

        // Pick starting point for current gap
        for (int i = 0; i < n - gap; i++)
        {

            // Set ending point
            int j = gap + i;

            // If current string is palindrome
            if (str[i] == str[j] && P[i + 1][j - 1])
                P[i][j] = true;
        }
    }
}

// A C++ function which recursively
// counts if a string str [i..j] is
// a k-palindromic string or not.
void countKPalindromes(int i, int j, int k)
{
    // terminating condition for a
    // string which is a k-palindrome.
    if (i == j)
    {
        Kpal[k]++;
        return;
    }

    // terminating condition for a
    // string which is not a k-palindrome.
    if (P[i][j] == false)
        return;

    // increases the counter for the
    // string if it is a k-palindrome.
    Kpal[k]++;

    // mid is middle pointer of
    // the string str [i...j].
    int mid = (i + j) / 2;

    // if length of string which is
    // (j - i + 1) is odd than we have
    // to subtract one from mid.
    // else if even then no change.
    if ((j - i + 1) % 2 == 1)
        mid--;

    // if the string is k-palindrome
    // then we check if it is a
    // (k+1) - palindrome or not by
    // just sending any of one half of
    // the string to the Count_k_Palindrome
    // function.
    countKPalindromes(i, mid, k + 1);
}

void printKPalindromes(string s)
{

    // Count of k-palindromes is equal
    // to zero initially.
    memset(Kpal, 0, sizeof(Kpal));

    // Finding all palindromic
    // substrings of given string
    int n = s.length();
    checkSubStrPal(s, n);

    // counting k-palindromes for each and
    // every substring of given string. .
    for (int i = 0; i < n; i++)
        for (int j = 0; j < n - i; j++)
            countKPalindromes(j, j + i, 1);

    // Output the number of K-palindromic
    // substrings of a given string.
    for (int i = 1; i <= n; i++)
        cout << Kpal[i] << " ";
    cout << "\n";
}

// Driver code
int main()
{
    string s = "abacaba";
    printKPalindromes(s);
    return 0;
}

Java

// Java program which counts 
// different palindromic 
// characteristics of a string.         
import java.io.*;

class GFG
{
    static int MAX_STR_LEN = 1000;
    
    static boolean P[][] = 
           new boolean[MAX_STR_LEN][MAX_STR_LEN];
    static int []Kpal = 
           new int[MAX_STR_LEN];
    
    // function which checks 
    // whether a substring 
    // str[i..j] of a given 
    // string is a palindrome or not.
    static void checkSubStrPal(String str, 
                               int n)
    {
    
        // P[i,j] = true if substring 
        // str [i..j] is palindrome, 
        // else false
        for (int i = 0; i < MAX_STR_LEN; i++) 
        {
            for (int j = 0; j < MAX_STR_LEN; j++)
                P[i][j] = false;
            Kpal[i] = 0;
        }
        
        // palindrome of 
        // single length
        for (int i = 0; i < n; i++)
            P[i][i] = true;
    
        // palindrome of 
        // length 2
        for (int i = 0; i < n - 1; i++)
            if (str.charAt(i) == str.charAt(i + 1))
                P[i][i + 1] = true;
    
        // Palindromes of length 
        // more then 2. This loop 
        // is similar to Matrix 
        // Chain Multiplication. 
        // We start with a gap of 
        // length 2 and fill P table 
        // in a way that gap between 
        // starting and ending indexes
        // increases one by one by 
        // outer loop.
        for (int gap = 2; gap < n; gap++)
        {
    
            // Pick starting point
            // for current gap
            for (int i = 0; i < n - gap; i++)
            {
    
                // Set ending point
                int j = gap + i;
    
                // If current string
                // is palindrome
                if (str.charAt(i) == str.charAt(j) && 
                                     P[i + 1][j - 1])
                    P[i][j] = true;
            }
        }
    }
    
    // A function which recursively
    // counts if a string str [i..j] is
    // a k-palindromic string or not.
    static void countKPalindromes(int i, int j, 
                                  int k)
    {
        // terminating condition 
        // for a string which is
        // a k-palindrome.
        if (i == j)
        {
            Kpal[k]++;
            return;
        }
    
        // terminating condition for 
        // a string which is not a 
        // k-palindrome.
        if (P[i][j] == false)
            return;
    
        // increases the counter 
        // for the string if it 
        // is a k-palindrome.
        Kpal[k]++;
    
        // mid is middle pointer of
        // the string str [i...j].
        int mid = (i + j) / 2;
    
        // if length of string which 
        // is (j - i + 1) is odd than
        // we have to subtract one 
        // from mid else if even then 
        // no change.
        if ((j - i + 1) % 2 == 1)
            mid--;
    
        // if the string is k-palindrome
        // then we check if it is a
        // (k+1) - palindrome or not 
        // by just sending any of one 
        // half of the string to the 
        // Count_k_Palindrome function.
        countKPalindromes(i, mid, k + 1);
    }
    
    static void printKPalindromes(String s)
    {
        // Finding all palindromic
        // substrings of given string
        int n = s.length();
        checkSubStrPal(s, n);
    
        // counting k-palindromes for 
        // each and every substring 
        // of given string. .
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n - i; j++)
                countKPalindromes(j, j + i, 1);
    
        // Output the number of 
        // K-palindromic substrings
        // of a given string.
        for (int i = 1; i <= n; i++)
            System.out.print(Kpal[i] + " ");
        System.out.println();
    }
    
    // Driver code
    public static void main(String args[])
    {
        String s = "abacaba";
        printKPalindromes(s);
    }
}

// This code is contributd by
// Manish Shaw(manishshaw1)

Python3

# Python program which counts 
# different palindromic 
# characteristics of a string.         
MAX_STR_LEN = 1000;

P = [[0 for x in range(MAX_STR_LEN)] 
        for y in range(MAX_STR_LEN)] ;

for i in range(0, MAX_STR_LEN) :
    for j in range(0, MAX_STR_LEN) :
        P[i][j] = False;
        
Kpal = [0] * MAX_STR_LEN;
    
# def which checks
# whether a substr[i..j] 
# of a given is a 
# palindrome or not.
def checkSubStrPal(str, n) :

    global P, Kpal, MAX_STR_LEN;
            
    # P[i,j] = True if substr
    # [i..j] is palindrome,
    # else False
    for i in range(0, MAX_STR_LEN) :

        for j in range(0, MAX_STR_LEN) :
            P[i][j] = False;
        Kpal[i] = 0;
    
    # palindrome of 
    # single length
    for i in range(0, n) :
        P[i][i] = True;

    # palindrome of
    # length 2
    for i in range(0, n - 1) :
        if (str[i] == str[i + 1]) :
            P[i][i + 1] = True;

    # Palindromes of length more 
    # then 2. This loop is similar 
    # to Matrix Chain Multiplication. 
    # We start with a gap of length 
    # 2 and fill P table in a way 
    # that gap between starting and 
    # ending indexes increases one 
    # by one by outer loop.
    for gap in range(2, n) :

        # Pick starting point
        # for current gap
        for i in range(0, n - gap) :

            # Set ending point
            j = gap + i;

            # If current string
            # is palindrome
            if (str[i] == str[j] and 
                P[i + 1][j - 1]) :
                P[i][j] = True;

# A Python def which 
# recursively counts if 
# a str [i..j] is a 
# k-palindromic or not.
def countKPalindromes(i, j, k) :

    global Kpal, P;
    
    # terminating condition 
    # for a which is a
    # k-palindrome.
    if (i == j) :
    
        Kpal[k] = Kpal[k] + 1;
        return;

    # terminating condition 
    # for a which is not a 
    # k-palindrome.
    if (P[i][j] == False) :
        return;

    # increases the counter
    # for the if it is a 
    # k-palindrome.
    Kpal[k] = Kpal[k] + 1;

    # mid is middle pointer 
    # of the str [i...j].
    mid = int((i + j) / 2);

    # if length of which is
    # (j - i + 1) is odd than 
    # we have to subtract one 
    # from mid else if even 
    # then no change.
    if ((j - i + 1) % 2 == 1) :
        mid = mid - 1;

    # if the is k-palindrome
    # then we check if it is a
    # (k+1) - palindrome or not 
    # by just sending any of 
    # one half of the to the 
    # Count_k_Palindrome def.
    countKPalindromes(i, mid, k + 1);

def printKPalindromes(s) :

    global P, Kpal, MAX_STR_LEN;
            
    # Finding all palindromic
    # substrings of given string
    n = len(s);
    checkSubStrPal(s, n);

    # counting k-palindromes 
    # for each and every sub 
    # of given string. .
    for i in range(0, n) :
        for j in range(0, n - i) :
            countKPalindromes(j, j + i, 1);

    # Output the number of 
    # K-palindromic substrings
    # of a given string.
    for i in range(1, n + 1) :
        print (Kpal[i], end=" ");
    print();


# Driver code
s = "abacaba";
printKPalindromes(s);

# This code is contributd by
# Manish Shaw(manishshaw1)

C#

// C# program which counts 
// different palindromic 
// characteristics of a string.         
using System;

class GFG
{
    static int MAX_STR_LEN = 1000;
    
    static bool [,]P = new bool[MAX_STR_LEN, 
                                MAX_STR_LEN];
    static int []Kpal = new int[MAX_STR_LEN];
    
    // function which checks whether
    // a substring str[i..j] of a 
    // given string is a palindrome or not.
    static void checkSubStrPal(string str, 
                               int n)
    {
    
        // P[i,j] = true if substring str
        // [i..j] is palindrome, else false
        for (int i = 0; i < MAX_STR_LEN; i++) 
        {
            for (int j = 0; j < MAX_STR_LEN; j++)
                P[i, j] = false;
            Kpal[i] = 0;
        }
        
        // palindrome of single length
        for (int i = 0; i < n; i++)
            P[i, i] = true;
    
        // palindrome of length 2
        for (int i = 0; i < n - 1; i++)
            if (str[i] == str[i + 1])
                P[i, i + 1] = true;
    
        // Palindromes of length more 
        // then 2. This loop is similar 
        // to Matrix Chain Multiplication. 
        // We start with a gap of length 2 
        // and fill P table in a way that
        // gap between starting and ending 
        // indexes increases one by one by
        // outer loop.
        for (int gap = 2; gap < n; gap++)
        {
    
            // Pick starting point
            // for current gap
            for (int i = 0; i < n - gap; i++)
            {
    
                // Set ending point
                int j = gap + i;
    
                // If current string
                // is palindrome
                if (str[i] == str[j] && 
                        P[i + 1, j - 1])
                    P[i, j] = true;
            }
        }
    }
    
    // A C++ function which recursively
    // counts if a string str [i..j] is
    // a k-palindromic string or not.
    static void countKPalindromes(int i, int j, 
                                  int k)
    {
        // terminating condition for a
        // string which is a k-palindrome.
        if (i == j)
        {
            Kpal[k]++;
            return;
        }
    
        // terminating condition for 
        // a string which is not a 
        // k-palindrome.
        if (P[i, j] == false)
            return;
    
        // increases the counter for the
        // string if it is a k-palindrome.
        Kpal[k]++;
    
        // mid is middle pointer of
        // the string str [i...j].
        int mid = (i + j) / 2;
    
        // if length of string which is
        // (j - i + 1) is odd than we have
        // to subtract one from mid.
        // else if even then no change.
        if ((j - i + 1) % 2 == 1)
            mid--;
    
        // if the string is k-palindrome
        // then we check if it is a
        // (k+1) - palindrome or not 
        // by just sending any of one 
        // half of the string to the 
        // Count_k_Palindrome function.
        countKPalindromes(i, mid, k + 1);
    }
    
    static void printKPalindromes(string s)
    {
        // Finding all palindromic
        // substrings of given string
        int n = s.Length;
        checkSubStrPal(s, n);
    
        // counting k-palindromes for each and
        // every substring of given string. .
        for (int i = 0; i < n; i++)
            for (int j = 0; j < n - i; j++)
                countKPalindromes(j, j + i, 1);
    
        // Output the number of K-palindromic
        // substrings of a given string.
        for (int i = 1; i <= n; i++)
            Console.Write(Kpal[i] + " ");
        Console.WriteLine();
    }
    
    // Driver code
    static void Main()
    {
        string s = "abacaba";
        printKPalindromes(s);
    }
}

// This code is contributd by
// Manish Shaw(manishshaw1)

PHP

<?php
// PHP program which counts 
// different palindromic 
// characteristics of a string.         
$MAX_STR_LEN = 1000;

$P = array(array());
$Kpal = array_fill(0, $MAX_STR_LEN, 0);

for($i = 0; $i < $MAX_STR_LEN; $i++) 
{
    for($j = 0; $j < $MAX_STR_LEN; $j++)
        $P[$i][$j] = false;
}
    
// function which checks
// whether a substr[i..j] 
// of a given is a 
// palindrome or not.
function checkSubStrPal($str, 
                        $n)
{
    global $P, $Kpal, 
           $MAX_STR_LEN;
           
    // P[i,j] = true if substr
    // [i..j] is palindrome, else false
    for ($i = 0; 
         $i < $MAX_STR_LEN; $i++) 
    {
        for ($j = 0; 
             $j < $MAX_STR_LEN; $j++)
            $P[$i][$j] = false;
        $Kpal[$i] = 0;
    }
    
    // palindrome of 
    // single length
    for ($i = 0; $i < $n; $i++)
        $P[$i][$i] = true;

    // palindrome of
    // length 2
    for ($i = 0; $i < $n - 1; $i++)
        if ($str[$i] == $str[$i + 1])
            $P[$i][$i + 1] = true;

    // Palindromes of length more 
    // then 2. This loop is similar 
    // to Matrix Chain Multiplication. 
    // We start with a gap of length 
    // 2 and fill P table in a way 
    // that gap between starting and 
    // ending indexes increases one 
    // by one by outer loop.
    for ($gap = 2; $gap < $n; $gap++)
    {
        // Pick starting point
        // for current gap
        for ($i = 0; 
             $i < $n - $gap; $i++)
        { 
            // Set ending point
            $j = $gap + $i;

            // If current string
            // is palindrome
            if ($str[$i] == $str[$j] && 
                    $P[$i + 1][$j - 1])
                $P[$i][$j] = true;
        }
    }
}

// A PHP function which 
// recursively counts if 
// a str [i..j] is a 
// k-palindromic or not.
function countKPalindromes($i, $j, $k)
{
    global $Kpal, $P;
    
    // terminating condition for a
    // which is a k-palindrome.
    if ($i == $j)
    {
        $Kpal[$k]++;
        return;
    }

    // terminating condition 
    // for a which is not a 
    // k-palindrome.
    if ($P[$i][$j] == false)
        return;

    // increases the counter
    // for the if it is a 
    // k-palindrome.
    $Kpal[$k]++;

    // mid is middle pointer 
    // of the str [i...j].
    $mid = ($i + $j) / 2;

    // if length of which is
    // (j - i + 1) is odd than 
    // we have to subtract one 
    // from mid else if even 
    // then no change.
    if (($j - $i + 1) % 2 == 1)
        $mid--;

    // if the is k-palindrome
    // then we check if it is a
    // (k+1) - palindrome or not 
    // by just sending any of 
    // one half of the to the 
    // Count_k_Palindrome function.
    countKPalindromes($i, $mid,
                      $k + 1);
}

function printKPalindromes($s)
{
    global $P, $Kpal, 
           $MAX_STR_LEN;
           
    // Finding all palindromic
    // substrings of given string
    $n = strlen($s);
    checkSubStrPal($s, $n);

    // counting k-palindromes 
    // for each and every sub 
    // of given string. .
    for ($i = 0; $i < $n; $i++)
        for ($j = 0; $j < $n - $i; $j++)
            countKPalindromes($j, $j + 
                              $i, 1);

    // Output the number of 
    // K-palindromic substrings
    // of a given string.
    for ($i = 1; $i <= $n; $i++)
        echo ($Kpal[$i] . " ");
    echo("\n");
}

// Driver code
$s = "abacaba";
printKPalindromes($s);

// This code is contributd by
// Manish Shaw(manishshaw1)
?>


Output :

12 4 1 0 0 0 0

Time Complexity : O(n^2$\log{n}$)
Auxiliary Space : O(n^2)



My Personal Notes arrow_drop_up

Check out this Author's contributed articles.

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.


Improved By : manishshaw1




Recommended Posts:



4.5 Average Difficulty : 4.5/5.0
Based on 2 vote(s)






User Actions