Count All Palindrome Sub-Strings in a String | Set 1
Given a string, the task is to count all palindrome sub string in a given string. Length of palindrome sub string is greater than or equal to 2.
Examples:
Input : str = "abaab" Output: 3 Explanation : All palindrome substring are : "aba" , "aa" , "baab" Input : str = "abbaeae" Output: 4 Explanation : All palindrome substring are : "bb" , "abba" ,"aea","eae"
We have discussed a similar problem below.
Find all distinct palindromic sub-strings of a given string
The above problem can be recursively defined.
Initial Values : i = 0, j = n-1; Given string 'str' CountPS(i, j) // If length of string is 2 then we // check both character are same or not If (j == i+1) return str[i] == str[j] // this condition shows that in recursion if i crosses // j then it will be a invalid substring or // if i==j that means only one character is remaining // and we require substring of length 2 //in both the conditions we need to return 0 Else if(i == j || i > j) return 0; Else If str[i..j] is PALINDROME // increment count by 1 and check for // rest palindromic substring (i, j-1), (i+1, j) // remove common palindrome substring (i+1, j-1) return countPS(i+1, j) + countPS(i, j-1) + 1 - countPS(i+1, j-1); Else // if NOT PALINDROME // We check for rest palindromic substrings (i, j-1) // and (i+1, j) // remove common palindrome substring (i+1 , j-1) return countPS(i+1, j) + countPS(i, j-1) - countPS(i+1 , j-1);
If we draw recursion tree of above recursive solution, we can observe overlapping Subproblems. Since the problem has overlapping sub-problems, we can solve it efficiently using Dynamic Programming.
Below is a Dynamic Programming based solution.
C++
// C++ program to find palindromic substrings of a string #include <bits/stdc++.h> using namespace std; // Returns total number of palindrome substring of // length greater than equal to 2 int CountPS( char str[], int n) { //to store the count of palindrome subarrays int ans=0; // P[i][j] = true if substring str[i..j] is palindrome, // else false bool P[n][n]; memset (P, false , sizeof (P)); // palindrome of single length for ( int i = 0; i < n; i++){ P[i][i] = true ; } // Palindromes of length more than or equal to 2. We start with // a gap of length 1 and fill the DP 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-1; // check If current string is palindrome of length 2 if (i==j-1){ P[i][j]=(str[i]==str[j]); } else { //check if the current substring is palindrome of length more than 2 //if characters at index i,j are equal check for string in between them //from i+1 to j-1 if it is palindrome or not P[i][j]=(str[i]==str[j] && P[i+1][j-1]); } //if substring from index i to j is palindrome increase the count if (P[i][j]){ ans++; } } } // return total palindromic substrings return ans; } // Driver code int main() { char str[] = "abaab" ; int n = strlen (str); cout << CountPS(str, n) << endl; return 0; } |
Java
// Java program to find palindromic substrings of a string public class GFG { // Returns total number of palindrome substring of // length greater than equal to 2 static int CountPS( char str[], int n) { // create empty 2-D matrix that counts all // palindrome substring. dp[i][j] stores counts of // palindromic substrings in st[i..j] int dp[][] = new int [n][n]; // P[i][j] = true if substring str[i..j] is // palindrome, else false boolean P[][] = new boolean [n][n]; // 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 ; dp[i][i + 1 ] = 1 ; } } // Palindromes of length more than 2. This loop is // similar to Matrix Chain Multiplication. We start // with a gap of length 2 and fill the DP 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 ; // Add current palindrome substring ( + 1) // and rest palindrome substring (dp[i][j-1] // + dp[i+1][j]) remove common palindrome // substrings (- dp[i+1][j-1]) if (P[i][j] == true ) dp[i][j] = dp[i][j - 1 ] + dp[i + 1 ][j] + 1 - dp[i + 1 ][j - 1 ]; else dp[i][j] = dp[i][j - 1 ] + dp[i + 1 ][j] - dp[i + 1 ][j - 1 ]; } } // return total palindromic substrings return dp[ 0 ][n - 1 ]; } // Driver code public static void main(String[] args) { String str = "abaab" ; System.out.println( CountPS(str.toCharArray(), str.length())); } } |
Python3
# Python3 program to find palindromic # substrings of a string # Returns total number of palindrome # substring of length greater than # equal to 2 def CountPS( str , n): # create empty 2-D matrix that counts # all palindrome substring. dp[i][j] # stores counts of palindromic # substrings in st[i..j] dp = [[ 0 for x in range (n)] for y in range (n)] # P[i][j] = true if substring str[i..j] # is palindrome, else false P = [[ False for x in range (n)] for y in range (n)] # palindrome of single length for i in range (n): P[i][i] = True # palindrome of length 2 for i in range (n - 1 ): if ( str [i] = = str [i + 1 ]): P[i][i + 1 ] = True dp[i][i + 1 ] = 1 # Palindromes of length more than 2. This # loop is similar to Matrix Chain Multiplication. # We start with a gap of length 2 and fill DP # table in a way that the gap between starting and # ending indexes increase one by one by # outer loop. for gap in range ( 2 , n): # Pick a starting point for the current gap for i in range (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 # Add current palindrome substring ( + 1) # and rest palindrome substring (dp[i][j-1] + # dp[i+1][j]) remove common palindrome # substrings (- dp[i+1][j-1]) if (P[i][j] = = True ): dp[i][j] = (dp[i][j - 1 ] + dp[i + 1 ][j] + 1 - dp[i + 1 ][j - 1 ]) else : dp[i][j] = (dp[i][j - 1 ] + dp[i + 1 ][j] - dp[i + 1 ][j - 1 ]) # return total palindromic substrings return dp[ 0 ][n - 1 ] # Driver Code if __name__ = = "__main__" : str = "abaab" n = len ( str ) print (CountPS( str , n)) # This code is contributed by ita_c |
C#
// C# program to find palindromic // substrings of a string using System; class GFG { // Returns total number of // palindrome substring of // length greater than equal to 2 public static int CountPS( char [] str, int n) { // create empty 2-D matrix that counts // all palindrome substring. dp[i][j] // stores counts of palindromic // substrings in st[i..j] int [][] dp = RectangularArrays.ReturnRectangularIntArray( n, n); // P[i][j] = true if substring str[i..j] // is palindrome, else false bool [][] P = RectangularArrays.ReturnRectangularBoolArray( n, n); // 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 ; dp[i][i + 1] = 1; } } // Palindromes of length more than 2. // This loop is similar to Matrix Chain // Multiplication. We start with a gap // of length 2 and fill DP 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 ; } // Add current palindrome substring // ( + 1) and rest palindrome substring // (dp[i][j-1] + dp[i+1][j]) remove common // palindrome substrings (- dp[i+1][j-1]) if (P[i][j] == true ) { dp[i][j] = dp[i][j - 1] + dp[i + 1][j] + 1 - dp[i + 1][j - 1]; } else { dp[i][j] = dp[i][j - 1] + dp[i + 1][j] - dp[i + 1][j - 1]; } } } // return total palindromic substrings return dp[0][n - 1]; } public static class RectangularArrays { public static int [][] ReturnRectangularIntArray( int size1, int size2) { int [][] newArray = new int [size1][]; for ( int array1 = 0; array1 < size1; array1++) { newArray[array1] = new int [size2]; } return newArray; } public static bool [][] ReturnRectangularBoolArray( int size1, int size2) { bool [][] newArray = new bool [size1][]; for ( int array1 = 0; array1 < size1; array1++) { newArray[array1] = new bool [size2]; } return newArray; } } // Driver Code public static void Main( string [] args) { string str = "abaab" ; Console.WriteLine( CountPS(str.ToCharArray(), str.Length)); } } // This code is contributed by Shrikant13 |
PHP
<?php // PHP program to find palindromic substrings // of a string // Returns total number of palindrome // substring of length greater than equal to 2 function CountPS( $str , $n ) { // create empty 2-D matrix that counts // all palindrome substring. dp[i][j] // stores counts of palindromic // substrings in st[i..j] $dp = array ( array ()); for ( $i = 0; $i < $n ; $i ++) for ( $j = 0; $j < $n ; $j ++) $dp [ $i ][ $j ] = 0; // P[i][j] = true if substring str[i..j] // is palindrome, else false $P = array ( array ()); for ( $i = 0; $i < $n ; $i ++) for ( $j = 0; $j < $n ; $j ++) $P [ $i ][ $j ] = false; // 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; $dp [ $i ][ $i + 1] = 1; } } // Palindromes of length more than 2. This // loop is similar to Matrix Chain Multiplication. // We start with a gap of length 2 and fill DP // 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; // Add current palindrome substring (+ 1) // and rest palindrome substring (dp[i][j-1] + // dp[i+1][j]) remove common palindrome // substrings (- dp[i+1][j-1]) if ( $P [ $i ][ $j ] == true) $dp [ $i ][ $j ] = $dp [ $i ][ $j - 1] + $dp [ $i + 1][ $j ] + 1 - $dp [ $i + 1][ $j - 1]; else $dp [ $i ][ $j ] = $dp [ $i ][ $j - 1] + $dp [ $i + 1][ $j ] - $dp [ $i + 1][ $j - 1]; } } // return total palindromic substrings return $dp [0][ $n - 1]; } // Driver Code $str = "abaab" ; $n = strlen ( $str ); echo CountPS( $str , $n ); // This code is contributed by Ryuga ?> |
Javascript
<script> // Javascript program to find palindromic substrings of a string // Returns total number of palindrome substring of // length greater than equal to 2 function CountPS(str,n) { // create empty 2-D matrix that counts all // palindrome substring. dp[i][j] stores counts of // palindromic substrings in st[i..j] let dp= new Array(n); // P[i][j] = true if substring str[i..j] is // palindrome, else false let P= new Array(n); for (let i=0;i<n;i++) { dp[i]= new Array(n); P[i]= new Array(n); for (let j=0;j<n;j++) { dp[i][j]=0; P[i][j]= false ; } } // palindrome of single length for (let i = 0; i < n; i++) P[i][i] = true ; // palindrome of length 2 for (let i = 0; i < n - 1; i++) { if (str[i] == str[i + 1]) { P[i][i + 1] = true ; dp[i][i + 1] = 1; } } // Palindromes of length more than 2. This loop is // similar to Matrix Chain Multiplication. We start // with a gap of length 2 and fill the DP table in a // way that gap between starting and ending indexes // increases one by one by outer loop. for (let gap = 2; gap < n; gap++) { // Pick starting point for current gap for (let i = 0; i < n - gap; i++) { // Set ending point let j = gap + i; // If current string is palindrome if (str[i] == str[j] && P[i + 1][j - 1]) P[i][j] = true ; // Add current palindrome substring ( + 1) // and rest palindrome substring (dp[i][j-1] // + dp[i+1][j]) remove common palindrome // substrings (- dp[i+1][j-1]) if (P[i][j] == true ) dp[i][j] = dp[i][j - 1] + dp[i + 1][j] + 1 - dp[i + 1][j - 1]; else dp[i][j] = dp[i][j - 1] + dp[i + 1][j] - dp[i + 1][j - 1]; } } // return total palindromic substrings return dp[0][n - 1]; } // Driver code let str = "abaab" ; document.write( CountPS(str.split( "" ), str.length)); // This code is contributed by avanitrachhadiya2155 </script> |
3
Time Complexity: O(n2)
Auxiliary Space: O(n2)
Method 2: This approach uses Top Down DP i.e memoized version of recursion.
Recursive soln: 1. Here base condition comes out to be i>j if we hit this condition, return 1. 2. We check for each and every i and j, if the characters are equal, if that is not the case, return 0. 3. Call the is_palindrome function again with incremented i and decremented j. 4. Check this for all values of i and j by applying 2 for loops.
Implementation:
C++
#include <bits/stdc++.h> using namespace std; int dp[1001][1001]; // 2D matrix bool isPal(string s, int i, int j) { // Base condition if (i > j) return 1; // check if the recursive tree // for given i, j // has already been executed if (dp[i][j] != -1) return dp[i][j]; // If first and last characters of // substring are unequal if (s[i] != s[j]) return dp[i][j] = 0; // memoization return dp[i][j] = isPal(s, i + 1, j - 1); } int countSubstrings(string s) { memset (dp, -1, sizeof (dp)); int n = s.length(); int count = 0; // 2 for loops are required to check for // all the palindromes in the string. for ( int i = 0; i < n; i++) { for ( int j = i + 1; j < n; j++) { // Increment count for every palindrome if (isPal(s, i, j)) count++; } } // return total palindromic substrings return count; } // Driver code int main() { string s = "abbaeae" ; cout << countSubstrings(s); //"bb" , "abba" ,"aea", "eae" are // the 4 palindromic substrings. // This code is contributed by Bhavneet Singh return 0; } |
Java
import java.util.*; public class Main { static int dp[][] = new int [ 1001 ][ 1001 ]; // 2D matrix public static int isPal(String s, int i, int j) { // Base condition if (i > j) return 1 ; // check if the recursive tree // for given i, j // has already been executed if (dp[i][j] != - 1 ) return dp[i][j]; // If first and last characters of // substring are unequal if (s.charAt(i) != s.charAt(j)) return dp[i][j] = 0 ; // memoization return dp[i][j] = isPal(s, i + 1 , j - 1 ); } public static int countSubstrings(String s) { for ( int [] row: dp) { Arrays.fill(row, - 1 ); } int n = s.length(); int count = 0 ; // 2 for loops are required to check for // all the palindromes in the string. for ( int i = 0 ; i < n; i++) { for ( int j = i + 1 ; j < n; j++) { // Increment count for every palindrome if (isPal(s, i, j) != 0 ) count++; } } // return total palindromic substrings return count; } public static void main(String[] args) { String s = "abbaeae" ; System.out.println(countSubstrings(s)); } } // This code is contributed by divyeshrabadiya07 |
Python3
# 2D matrix dp = [[ - 1 for i in range ( 1001 )] for j in range ( 1001 )] def isPal(s, i, j): # Base condition if (i > j): return 1 # Check if the recursive tree # for given i, j # has already been executed if (dp[i][j] ! = - 1 ): return dp[i][j] # If first and last characters of # substring are unequal if (s[i] ! = s[j]): dp[i][j] = 0 return dp[i][j] # Memoization dp[i][j] = isPal(s, i + 1 , j - 1 ) return dp[i][j] def countSubstrings(s): n = len (s) count = 0 # 2 for loops are required to check for # all the palindromes in the string. for i in range (n): for j in range (i + 1 , n): # Increment count for every palindrome if (isPal(s, i, j)): count + = 1 # Return total palindromic substrings return count # Driver code s = "abbaeae" print (countSubstrings(s)) # This code is contributed by rag2127 |
C#
using System; class GFG{ // 2D matrix static int [,] dp = new int [1001, 1001]; static int isPal( string s, int i, int j) { // Base condition if (i > j) return 1; // Check if the recursive tree // for given i, j // has already been executed if (dp[i, j] != -1) return dp[i, j]; // If first and last characters of // substring are unequal if (s[i] != s[j]) return dp[i, j] = 0; // Memoization return dp[i, j] = isPal(s, i + 1, j - 1); } static int countSubstrings( string s) { for ( int i = 0; i < 1001; i++) { for ( int j = 0; j < 1001; j++) { dp[i, j] = -1; } } int n = s.Length; int count = 0; // 2 for loops are required to check for // all the palindromes in the string. for ( int i = 0; i < n; i++) { for ( int j = i + 1; j < n; j++) { // Increment count for every palindrome if (isPal(s, i, j) != 0) count++; } } // Return total palindromic substrings return count; } // Driver Code static void Main() { string s = "abbaeae" ; Console.WriteLine(countSubstrings(s)); } } // This code is contributed by divyesh072019 |
Javascript
<script> var dp = Array(1001).fill().map(()=>Array(1001).fill(-1)); // 2D matrix function isPal( s , i , j) { // Base condition if (i > j) return 1; // check if the recursive tree // for given i, j // has already been executed if (dp[i][j] != -1) return dp[i][j]; // If first and last characters of // substring are unequal if (s.charAt(i) != s.charAt(j)) return dp[i][j] = 0; // memoization return dp[i][j] = isPal(s, i + 1, j - 1); } function countSubstrings( s) { var n = s.length; var count = 0; // 2 for loops are required to check for // all the palindromes in the string. for (i = 0; i < n; i++) { for (j = i + 1; j < n; j++) { // Increment count for every palindrome if (isPal(s, i, j) != 0) count++; } } // return total palindromic substrings return count; } // Driver code var s = "abbaeae" ; document.write(countSubstrings(s)); // This code is contributed by Rajput-Ji </script> |
4
Time Complexity: O(n3)
Auxiliary Space: O(n2)
Count All Palindrome Sub-Strings in a String | Set 2
This article is contributed by Nishant_Singh(Pintu). If you like GeeksforGeeks 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 GeeksforGeeks main page and help other Geeks.
Please Login to comment...