Open In App

Palindrome Substrings Count

Last Updated : 04 Aug, 2025
Comments
Improve
Suggest changes
Like Article
Like
Report

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));

Output
3

[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));

Output
3

[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));

Output
3

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:


Similar Reads