Given a string str, the task is to find the number of odd length palindromic sub-sequences around of str with str[i] as center i.e. every index will be considered as the center one by one.
Examples:
Input: str = “xyzx”
Output: 1 2 2 1
For index 0: There is only a single sub-sequence possible i.e. “x”
For index 1: Two sub-sequences are possible i.e. “y” and “xyx”
For index 2: “z” and “xzx”
For index 3: “x”Input: str = “aaaa”
Output: 1 3 3 1
Approach: We will use dynamic programming to solve this problem. Let’s denote length of the string str be N. Now, Let dp[i][j] denote the number of palindromic sub-sequences from 0 to i – 1 and number of palindromic sub-sequences from j to N – 1.
Let len be the distance between i and j. For each length len, we will fix our i and j, and check whether characters str[i] and str[j] are equal or not. Then according to it, we will make our dp transitions.
If str[i] != str[j] then dp[i][j] = dp[i – 1][j] + dp[i][j + 1] – dp[i – 1][j + 1]
If str[i] == str[j] then dp[i][j] = dp[i – 1][j] + dp[i][j + 1]
Base case:
If i == 0 and j == n – 1 then dp[i][j] = 2 if str[i] == str[j] else dp[i][j] = 1.
Below is the implementation of the above approach:
C++
// C++ implementation of the approach #include <bits/stdc++.h> using namespace std; // Function to find the total palindromic // odd length sub-sequences void solve(string& s) { int n = s.length(); // dp array to store the number of palindromic // subsequences for 0 to i-1 and j+1 to n-1 int dp[n][n]; memset (dp, 0, sizeof dp); // We will start with the largest // distance between i and j for ( int len = n - 1; len >= 0; --len) { // For each len, we fix our i for ( int i = 0; i + len < n; ++i) { // For this i we will find our j int j = i + len; // Base cases if (i == 0 and j == n - 1) { if (s[i] == s[j]) dp[i][j] = 2; else if (s[i] != s[j]) dp[i][j] = 1; } else { if (s[i] == s[j]) { // If the characters are equal // then look for out of bound index if (i - 1 >= 0) { dp[i][j] += dp[i - 1][j]; } if (j + 1 <= n - 1) { dp[i][j] += dp[i][j + 1]; } if (i - 1 < 0 or j + 1 >= n) { // We have only 1 way that is to // just pick these characters dp[i][j] += 1; } } else if (s[i] != s[j]) { // If the characters are not equal if (i - 1 >= 0) { dp[i][j] += dp[i - 1][j]; } if (j + 1 <= n - 1) { dp[i][j] += dp[i][j + 1]; } if (i - 1 >= 0 and j + 1 <= n - 1) { // Subtract it as we have // counted it twice dp[i][j] -= dp[i - 1][j + 1]; } } } } } vector< int > ways; for ( int i = 0; i < n; ++i) { if (i == 0 or i == n - 1) { // We have just 1 palindrome // sequence of length 1 ways.push_back(1); } else { // Else total ways would be sum of dp[i-1][i+1], // that is number of palindrome sub-sequences // from 1 to i-1 + number of palindrome // sub-sequences from i+1 to n-1 int total = dp[i - 1][i + 1]; ways.push_back(total); } } for ( int i = 0; i < ways.size(); ++i) { cout << ways[i] << " " ; } } // Driver code int main() { string s = "xyxyx" ; solve(s); return 0; } |
Java
// Java implementation of above approach import java.util.*; class GFG { // Function to find the total palindromic // odd length sub-sequences static void solve( char [] s) { int n = s.length; // dp array to store the number of palindromic // subsequences for 0 to i-1 and j+1 to n-1 int [][]dp = new int [n][n]; // We will start with the largest // distance between i and j for ( int len = n - 1 ; len >= 0 ; --len) { // For each len, we fix our i for ( int i = 0 ; i + len < n; ++i) { // For this i we will find our j int j = i + len; // Base cases if (i == 0 && j == n - 1 ) { if (s[i] == s[j]) dp[i][j] = 2 ; else if (s[i] != s[j]) dp[i][j] = 1 ; } else { if (s[i] == s[j]) { // If the characters are equal // then look for out of bound index if (i - 1 >= 0 ) { dp[i][j] += dp[i - 1 ][j]; } if (j + 1 <= n - 1 ) { dp[i][j] += dp[i][j + 1 ]; } if (i - 1 < 0 || j + 1 >= n) { // We have only 1 way that is to // just pick these characters dp[i][j] += 1 ; } } else if (s[i] != s[j]) { // If the characters are not equal if (i - 1 >= 0 ) { dp[i][j] += dp[i - 1 ][j]; } if (j + 1 <= n - 1 ) { dp[i][j] += dp[i][j + 1 ]; } if (i - 1 >= 0 && j + 1 <= n - 1 ) { // Subtract it as we have // counted it twice dp[i][j] -= dp[i - 1 ][j + 1 ]; } } } } } Vector<Integer> ways = new Vector<>(); for ( int i = 0 ; i < n; ++i) { if (i == 0 || i == n - 1 ) { // We have just 1 palindrome // sequence of length 1 ways.add( 1 ); } else { // Else total ways would be sum of dp[i-1][i+1], // that is number of palindrome sub-sequences // from 1 to i-1 + number of palindrome // sub-sequences from i+1 to n-1 int total = dp[i - 1 ][i + 1 ]; ways.add(total); } } for ( int i = 0 ; i < ways.size(); ++i) { System.out.print(ways.get(i) + " " ); } } // Driver code public static void main(String[] args) { char [] s = "xyxyx" .toCharArray(); solve(s); } } // This code has been contributed by 29AjayKumar |
Python3
# Function to find the total palindromic # odd Length sub-sequences def solve(s): n = len (s) # dp array to store the number of palindromic # subsequences for 0 to i-1 and j+1 to n-1 dp = [[ 0 for i in range (n)] for i in range (n)] # We will start with the largest # distance between i and j for Len in range (n - 1 , - 1 , - 1 ): # For each Len, we fix our i for i in range (n): if i + Len > = n: break # For this i we will find our j j = i + Len # Base cases if (i = = 0 and j = = n - 1 ): if (s[i] = = s[j]): dp[i][j] = 2 elif (s[i] ! = s[j]): dp[i][j] = 1 else : if (s[i] = = s[j]): # If the characters are equal # then look for out of bound index if (i - 1 > = 0 ): dp[i][j] + = dp[i - 1 ][j] if (j + 1 < = n - 1 ): dp[i][j] + = dp[i][j + 1 ] if (i - 1 < 0 or j + 1 > = n): # We have only 1 way that is to # just pick these characters dp[i][j] + = 1 elif (s[i] ! = s[j]): # If the characters are not equal if (i - 1 > = 0 ): dp[i][j] + = dp[i - 1 ][j] if (j + 1 < = n - 1 ): dp[i][j] + = dp[i][j + 1 ] if (i - 1 > = 0 and j + 1 < = n - 1 ): # Subtract it as we have # counted it twice dp[i][j] - = dp[i - 1 ][j + 1 ] ways = [] for i in range (n): if (i = = 0 or i = = n - 1 ): # We have just 1 palindrome # sequence of Length 1 ways.append( 1 ) else : # Else total ways would be sum of dp[i-1][i+1], # that is number of palindrome sub-sequences # from 1 to i-1 + number of palindrome # sub-sequences from i+1 to n-1 total = dp[i - 1 ][i + 1 ] ways.append(total) for i in ways: print (i,end = " " ) # Driver code s = "xyxyx" solve(s) # This code is contributed by mohit kumar 29 |
C#
// C# implementation of above approach using System; using System.Collections.Generic; class GFG { // Function to find the total palindromic // odd length sub-sequences static void solve( char [] s) { int n = s.Length; // dp array to store the number of palindromic // subsequences for 0 to i-1 and j+1 to n-1 int [,]dp = new int [n, n]; // We will start with the largest // distance between i and j for ( int len = n - 1; len >= 0; --len) { // For each len, we fix our i for ( int i = 0; i + len < n; ++i) { // For this i we will find our j int j = i + len; // Base cases if (i == 0 && j == n - 1) { if (s[i] == s[j]) dp[i, j] = 2; else if (s[i] != s[j]) dp[i, j] = 1; } else { if (s[i] == s[j]) { // If the characters are equal // then look for out of bound index if (i - 1 >= 0) { dp[i, j] += dp[i - 1, j]; } if (j + 1 <= n - 1) { dp[i, j] += dp[i, j + 1]; } if (i - 1 < 0 || j + 1 >= n) { // We have only 1 way that is to // just pick these characters dp[i, j] += 1; } } else if (s[i] != s[j]) { // If the characters are not equal if (i - 1 >= 0) { dp[i, j] += dp[i - 1, j]; } if (j + 1 <= n - 1) { dp[i, j] += dp[i, j + 1]; } if (i - 1 >= 0 && j + 1 <= n - 1) { // Subtract it as we have // counted it twice dp[i, j] -= dp[i - 1, j + 1]; } } } } } List< int > ways = new List< int >(); for ( int i = 0; i < n; ++i) { if (i == 0 || i == n - 1) { // We have just 1 palindrome // sequence of length 1 ways.Add(1); } else { // Else total ways would be sum of dp[i-1][i+1], // that is number of palindrome sub-sequences // from 1 to i-1 + number of palindrome // sub-sequences from i+1 to n-1 int total = dp[i - 1,i + 1]; ways.Add(total); } } for ( int i = 0; i < ways.Capacity; ++i) { Console.Write(ways[i] + " " ); } } // Driver code public static void Main() { char [] s = "xyxyx" .ToCharArray(); solve(s); } } // This code is contributed by AnkitRai01 |
Javascript
<script> // Javascript implementation of above approach // Function to find the total palindromic // odd length sub-sequences function solve(s) { n = s.length; // dp array to store the number of palindromic // subsequences for 0 to i-1 and j+1 to n-1 let dp = new Array(n); for (let i=0;i<n;i++) { dp[i]= new Array(n); for (let j=0;j<n;j++) dp[i][j]=0; } // We will start with the largest // distance between i and j for (let len = n - 1; len >= 0; --len) { // For each len, we fix our i for (let i = 0; i + len < n; ++i) { // For this i we will find our j let j = i + len; // Base cases if (i == 0 && j == n - 1) { if (s[i] == s[j]) dp[i][j] = 2; else if (s[i] != s[j]) dp[i][j] = 1; } else { if (s[i] == s[j]) { // If the characters are equal // then look for out of bound index if (i - 1 >= 0) { dp[i][j] += dp[i - 1][j]; } if (j + 1 <= n - 1) { dp[i][j] += dp[i][j + 1]; } if (i - 1 < 0 || j + 1 >= n) { // We have only 1 way that is to // just pick these characters dp[i][j] += 1; } } else if (s[i] != s[j]) { // If the characters are not equal if (i - 1 >= 0) { dp[i][j] += dp[i - 1][j]; } if (j + 1 <= n - 1) { dp[i][j] += dp[i][j + 1]; } if (i - 1 >= 0 && j + 1 <= n - 1) { // Subtract it as we have // counted it twice dp[i][j] -= dp[i - 1][j + 1]; } } } } } let ways = []; for (let i = 0; i < n; ++i) { if (i == 0 || i == n - 1) { // We have just 1 palindrome // sequence of length 1 ways.push(1); } else { // Else total ways would be sum of dp[i-1][i+1], // that is number of palindrome sub-sequences // from 1 to i-1 + number of palindrome // sub-sequences from i+1 to n-1 let total = dp[i - 1][i + 1]; ways.push(total); } } for (let i = 0; i < ways.length; ++i) { document.write(ways[i] + " " ); } } // Driver code let s = "xyxyx" .split( "" ); solve(s); // This code is contributed by rag2127 </script> |
1 3 4 3 1
Time Complexity: O(n2)
Auxiliary Space: O(n2), where n is the length of the given string.
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 neveropen!