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++ 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 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 |
# 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# 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 |
<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.