Palindrome Substrings Count
Last Updated : 29 Aug, 2025
Given a string s, find the total number of palindromic substrings of length greater than or equal to 2 present in the string.
A substring is palindromic if it reads the same forwards and backwards.
Examples:
Input: s = "abaab"
Output: 3
Explanation: Palindromic substrings with length greater than 1, are "aba", "aa", and "baab".
Input: s = "aaa"
Output: 3
Explanation: Palindromic substrings with length greater than 1, are "aa" , "aa" , "aaa" .
Input: s = "abbaeae"
Output: 4
Explanation: Palindromic substrings with length greater than 1, are "bb" , "abba" , "aea", "eae".
[Naive Approach] By Generating All Possible Substrings - O(n^3) Time and O(1) Space
The idea is to generate all possible substrings using two nested loops and for every substring check if it is palindrome or not.
C++ // C++ program to count all palindromic substring of // given string by generating all possible substrings #include <iostream> #include <string> using namespace std; // Function to check if a substring // s[i..j] is a palindrome bool isPalindrome(string& s, int i, int j) { while (i < j) { if (s[i] != s[j]) return false; i++; j--; } return true; } int countPS(string& s) { int n = s.length(); // Consider all possible substrings of lengths // more than 1 int res = 0; for (int i = 0; i < n; i++) { for (int j = i+1; j < n; j++) { // If substring from i to j is palindrome // increment the result if (isPalindrome(s, i, j)) res++; } } return res; } int main() { string s = "abaab"; cout << countPS(s); return 0; }
Java // Java program to count all palindromic substring of // given string by generating all possible substrings class GfG { // Function to check if a substring // s[i..j] is a palindrome static boolean isPalindrome(String s, int i, int j) { while (i < j) { if (s.charAt(i) != s.charAt(j)) return false; i++; j--; } return true; } static int countPS(String s) { int n = s.length(); // Consider all possible substrings of lengths // more than 1 int res = 0; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { // If substring from i to j is palindrome // increment the result if (isPalindrome(s, i, j)) res++; } } return res; } public static void main(String[] args) { String s = "abaab"; System.out.println(countPS(s)); } }
Python # Python program to count all palindromic substring of # given string by generating all possible substrings # Function to check if a substring # s[i..j] is a palindrome def isPalindrome(s, i, j): while i < j: if s[i] != s[j]: return False i += 1 j -= 1 return True def countPS(s): n = len(s) # Consider all possible substrings of lengths # more than 1 res = 0 for i in range(n): for j in range(i + 1, n): # If substring from i to j is palindrome # increment the result if isPalindrome(s, i, j): res += 1 return res if __name__ == "__main__": s = "abaab" print(countPS(s))
C# // C# program to count all palindromic substring of // given string by generating all possible substrings using System; class GfG { // Function to check if a substring // s[i..j] is a palindrome static bool isPalindrome(string s, int i, int j) { while (i < j) { if (s[i] != s[j]) return false; i++; j--; } return true; } static int countPS(string s) { int n = s.Length; // Consider all possible substrings of lengths // more than 1 int res = 0; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { // If substring from i to j is palindrome // increment the result if (isPalindrome(s, i, j)) res++; } } return res; } static void Main() { string s = "abaab"; Console.WriteLine(countPS(s)); } }
JavaScript // JavaScript program to count all palindromic substring // of given string by generating all possible substrings function isPalindrome(s, i, j) { while (i < j) { if (s[i] !== s[j]) return false; i++; j--; } return true; } function countPS(s) { let n = s.length; // Consider all possible substrings of lengths // more than 1 let res = 0; for (let i = 0; i < n; i++) { for (let j = i + 1; j < n; j++) { // If substring from i to j is palindrome // increment the result if (isPalindrome(s, i, j)) res++; } } return res; } // Driver Code let s = "abaab"; console.log(countPS(s));
[Better Approach 1] Using Memoization - O(n^2) Time and O(n^2) Space
If we notice carefully, we can observe that this recursive solution holds the following two properties of Dynamic Programming:
1.Optimal Substructure: The solution for the problem isPalindrome(i, j) depends on the optimal solution of the subproblem isPalindrome(i + 1, j - 1). By solving the smaller substructures, we can efficiently find if the entire substring is a palindrome or not.
2.Overlapping Subproblems: We can see that we are computing the same subproblems multiple times, isPalindrome(i + 2, j - 2) will be computed in isPalindrome(i, j) as well as isPalindrome(i + 1, j - 1). This redundancy leads to overlapping subproblems.
- There are two parameters(i and j) that change in the recursive solution and then can go from 0 to n. So we create a 2D array of size n x n for memoization.
- We initialize this array as -1 to indicate nothing is computed initially. We first check if the value is -1, then only we make recursive calls.
- If the substring from i to j is a palindrome, we store memo[i][j] = 1, otherwise 0.
C++ // C++ program to count all palindromic substring of // given string using memoization #include <iostream> #include <vector> #include <string> using namespace std; int isPalindrome(int i, int j, string& s, vector<vector<int>>& memo) { // One length string is always palindrome if (i == j) return 1; // Two length string is plaindrome if // both characters are same if (j == i + 1 && s[i] == s[j]) return 1; // if current substring is already checked if (memo[i][j] != -1) return memo[i][j]; // Check if the characters at i and j are equal // and the substring inside is palindrome memo[i][j] = (s[i] == s[j] && isPalindrome(i + 1, j - 1, s, memo)); return memo[i][j]; } int countPS(string& s) { int n = s.length(); // Memoization table vector<vector<int>> memo(n, vector<int>(n, -1)); int res = 0; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { // Check if the substring is palindrome if (isPalindrome(i, j, s, memo)) { res++; } } } return res; } int main() { string s = "abaab"; cout << countPS(s); return 0; }
Java // Java program to count all palindromic substring of given // string using memoization import java.util.Arrays; class GfG { static int isPalindrome(int i, int j, String s, int[][] memo) { // One length string is always palindrome if (i == j) return 1; // Two length string is palindrome if // both characters are same if (j == i + 1 && s.charAt(i) == s.charAt(j)) return 1; // if current substring is already checked if (memo[i][j] != -1) return memo[i][j]; // Check if the characters at i and j are equal // and the substring inside is palindrome if(s.charAt(i) == s.charAt(j) && isPalindrome(i + 1, j - 1, s, memo) == 1) memo[i][j] = 1; else memo[i][j] = 0; return memo[i][j]; } static int countPS(String s) { int n = s.length(); // Memoization table int[][] memo = new int[n][n]; for (int[] row : memo) { Arrays.fill(row, -1); } int res = 0; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { // Check if the substring is palindrome if (isPalindrome(i, j, s, memo) == 1) { res++; } } } return res; } public static void main(String[] args) { String s = "abaab"; System.out.println(countPS(s)); } }
Python # Python program to count all palindromic substrings of # a given string using memoization def isPalindrome(i, j, s, memo): # One length string is always palindrome if i == j: return 1 # Two length string is palindrome if # both characters are same if j == i + 1 and s[i] == s[j]: return 1 # if current substring is already checked if memo[i][j] != -1: return memo[i][j] # Check if the characters at i and j are equal # and the substring inside is palindrome if s[i] == s[j] and isPalindrome(i + 1, j - 1, s, memo) == 1: memo[i][j] = 1 else: memo[i][j] = 0 return memo[i][j] def countPS(s): n = len(s) # Memoization table memo = [[-1 for i in range(n)] for i in range(n)] res = 0 for i in range(n): for j in range(i + 1, n): # Check if the substring is palindrome if isPalindrome(i, j, s, memo) == 1: res += 1 return res if __name__ == "__main__": s = "abaab" print(countPS(s))
C# // C# program to count all palindromic substrings of // a given string using memoization using System; class GfG { static int IsPalindrome(int i, int j, string s, int[,] memo) { // One length string is always palindrome if (i == j) return 1; // Two length string is palindrome if // both characters are same if (j == i + 1 && s[i] == s[j]) return 1; // if current substring is already checked if (memo[i, j] != -1) return memo[i, j]; // Check if the characters at i and j are equal // and the substring inside is palindrome if (s[i] == s[j] && IsPalindrome(i + 1, j - 1, s, memo) == 1) { memo[i, j] = 1; } else { memo[i, j] = 0; } return memo[i, j]; } static int CountPS(string s) { int n = s.Length; // Memoization table int[,] memo = new int[n, n]; for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { memo[i, j] = -1; } } int res = 0; for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { // Check if the substring is palindrome if (IsPalindrome(i, j, s, memo) == 1) { res++; } } } return res; } static void Main() { string s = "abaab"; Console.WriteLine(CountPS(s)); } }
JavaScript // JavaScript program to count all palindromic substrings of // a given string using memoization function isPalindrome(i, j, s, memo) { // One length string is always palindrome if (i === j) return 1; // Two length string is palindrome if // both characters are same if (j === i + 1 && s[i] === s[j]) return 1; // if current substring is already checked if (memo[i][j] !== -1) return memo[i][j]; // Check if the characters at i and j are equal // and the substring inside is palindrome if (s[i] === s[j] && isPalindrome(i + 1, j - 1, s, memo) === 1) memo[i][j] = 1; else memo[i][j] = 0; return memo[i][j]; } function countPS(s) { const n = s.length; // Memoization table const memo = Array.from({ length: n }, () => Array(n).fill(-1)); let res = 0; for (let i = 0; i < n; i++) { for (let j = i + 1; j < n; j++) { // Check if the substring is palindrome if (isPalindrome(i, j, s, memo) === 1) { res++; } } } return res; } // Driver Code const s = "abaab"; console.log(countPS(s));
[Better Approach 2] Using Bottom-Up DP (Tabulation) - O(n^2) Time and O(n^2) Space
We create a dp array of size n x n. However, we cannot simply fill the dp table from i = 0 to n-1 and j from i to n-1. To compute the value for (i, j), we need the value from (i+1, j-1). Similar to Matrix Chain Multiplication, we need to fill the table diagonally using a gap variable.
1. Base Cases:
=> A single character string is always palindrome, i.e. dp[i][i] = true.
=> Strings having two characters are palindrome, if both the characters are same. i.e. dp[i][i+1] = true if s[i] == s[i+1].
2. Any substring s[i...j] will be palindrome if:
=> If first and last characters of string are same
=> Remaining substring (excluding first and last character) is palindrome. I.e. dp[i+1][j-1] = true.
Illustration:
C++ // C++ program to count all palindromic substring of // given string using bottom up DP #include <iostream> #include <vector> #include <string> using namespace std; int countPS(string& s) { int n = s.length(); int res = 0; vector<vector<bool>> dp(n, vector<bool>(n, false)); // One length string is always palindrome for (int i = 0; i < n; i++) { dp[i][i] = true; } // Two length string is plaindrome if // both characters are same for (int i = 0; i < n - 1; i++) { if (s[i] == s[i + 1]) { dp[i][i + 1] = true; res++; } } // Handle palindromes of length // greater than 2 (gap >= 2) for (int gap = 2; gap < n; gap++) { for (int i = 0; i < n - gap; i++) { int j = i + gap; // Check if the current string is a palindrome if (s[i] == s[j] && dp[i + 1][j - 1]) { dp[i][j] = true; res++; } } } return res; } int main() { string s = "abaab"; cout << countPS(s) << endl; return 0; }
Java // Java program to count all palindromic substrings of // given string using bottom-up DP import java.util.*; class GfG { static int countPS(String s) { int n = s.length(); int res = 0; boolean[][] dp = new boolean[n][n]; // One length string is always palindrome for (int i = 0; i < n; i++) { dp[i][i] = true; } // Two length string is palindrome if // both characters are same for (int i = 0; i < n - 1; i++) { if (s.charAt(i) == s.charAt(i + 1)) { dp[i][i + 1] = true; res++; } } // Handle palindromes of length greater than 2 for (int gap = 2; gap < n; gap++) { for (int i = 0; i < n - gap; i++) { int j = i + gap; // Check if the current string is a palindrome if (s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1]) { dp[i][j] = true; res++; } } } return res; } public static void main(String[] args) { String s = "abaab"; System.out.println(countPS(s)); } }
Python # Python program to count all palindromic substrings of # given string using bottom-up DP def countPS(s): n = len(s) res = 0 dp = [[False] * n for i in range(n)] # One length string is always palindrome for i in range(n): dp[i][i] = True # Two length string is palindrome if # both characters are same for i in range(n - 1): if s[i] == s[i + 1]: dp[i][i + 1] = True res += 1 # Handle palindromes of length # greater than 2 (gap >= 2) for gap in range(2, n): for i in range(n - gap): j = i + gap # Check if the current string is a palindrome if s[i] == s[j] and dp[i + 1][j - 1]: dp[i][j] = True res += 1 return res if __name__ == "__main__": s = "abaab" print(countPS(s))
C# // C# program to count all palindromic substrings of // given string using bottom-up DP using System; class GfG { static int countPS(string s) { int n = s.Length; int res = 0; bool[,] dp = new bool[n, n]; // One length string is always palindrome for (int i = 0; i < n; i++) { dp[i, i] = true; } // Two length string is palindrome if // both characters are same for (int i = 0; i < n - 1; i++) { if (s[i] == s[i + 1]) { dp[i, i + 1] = true; res++; } } // Handle palindromes of length // greater than 2 (gap >= 2) for (int gap = 2; gap < n; gap++) { for (int i = 0; i < n - gap; i++) { int j = i + gap; // Check if the current string is a palindrome if (s[i] == s[j] && dp[i + 1, j - 1]) { dp[i, j] = true; res++; } } } return res; } static void Main() { string s = "abaab"; Console.WriteLine(countPS(s)); } }
JavaScript // JavaScript program to count all palindromic substrings of // given string using bottom-up DP function countPS(s) { const n = s.length; let res = 0; const dp = Array.from({ length: n }, () => Array(n).fill(false)); // One length string is always palindrome for (let i = 0; i < n; i++) { dp[i][i] = true; } // Two length string is palindrome if // both characters are same for (let i = 0; i < n - 1; i++) { if (s[i] === s[i + 1]) { dp[i][i + 1] = true; res++; } } // Handle palindromes of length // greater than 2 (gap >= 2) for (let gap = 2; gap < n; gap++) { for (let i = 0; i < n - gap; i++) { const j = i + gap; // Check if the current string is a palindrome if (s[i] === s[j] && dp[i + 1][j - 1]) { dp[i][j] = true; res++; } } } return res; } // Driver Code const s = "abaab"; console.log(countPS(s));
Expected Approach - Continued article
This problem can be solved more efficiently using Manacher’s algorithm or the center expansion technique.
See: Count All Palindrome Sub-Strings Set 2
Related article:
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem