Let be the input string. A substring s_i ... s_j is a palindrome if at least one of the following conditions is satisfied:
i \ge j, that is, the substring is empty or consists of a single character;
s_i = s_j and the substring s_{i + 1} ... s_{j - 1} is a palindrome;
Let's define the function IsPal, that returns if the substring s_i ... s_j is a palindrome, and otherwise.
To speed up the algorithm, the values of IsPal(i, j) are stored in the cells of a two-dimensional array pal[i][j].
A string is called a superpalindrome if it can be represented as a concatenation of one or more palindromes. For example, the following strings are superpalindromes:
Let
Here it is assumed that i < j, that is, the length of the substring is at least two.
Let us note the base cases:
If i \ge j, then the substring is either empty or consists of a single character. Such strings are not considered palindromes by definition. Therefore,
In particular, for any position , we have dp[i][i] = 0.
If the substring s_i ... s_j is a palindrome and its length is at least two, then it is automatically a superpalindrome (since it consists of a single palindrome). Therefore, for all pairs of indices where 0 \le i < j < n, if the substring s_i ... s_j is a palindrome, we can immediately set dp[i][j] = 1.
Now consider the general case. Let the substring s_i ... s_j not be a palindrome as a whole. It can still be a superpalindrome if it can be split into two parts, each of which is a superpalindrome.
To do this, iterate over all possible split positions such that i < k < j - 1.
The restriction k < j - 1 ensures that both substrings
have length at least two, and therefore can potentially be superpalindromes.
If, for some , the following conditions are satisfied:
dp[i][k] = 1,
dp[k + 1][j] = 1,
then the substring s_i ... s_j can be represented as a concatenation of two superpalindromes. Therefore, it is itself a superpalindrome, and we set dp[i][j] = 1.
If this condition is not satisfied for any valid , then dp[i][j] remains .
Finally, count the number of pairs for which i < j and dp[i][j] = 1. This count is exactly the number of substrings of the string that are superpalindromes.
Example
For the given example — the string "" — there are substrings that are superpalindromes:
For the string "", there are substrings that are superpalindromes:
Algorithm implementation
Declare the arrays.
#define MAX 1010
char s[MAX];
int dp[MAX][MAX];
int pal[MAX][MAX];The function IsPal checks whether the substring s_i \ldots s_j is a palindrome. The substring s_i \ldots s_j is a palindrome if s_i = s_j and the substring s_{i + 1} \ldots s_{j - 1} is also a palindrome. The values of the function IsPal are stored in the cells of the two-dimensional array pal[i][j].
int IsPal(int i, int j)
{
if (i >= j) return pal[i][j] = 1;
if (pal[i][j] != -1) return pal[i][j];
return pal[i][j] = (s[i] == s[j]) && IsPal(i + 1,j - 1);
}The main part of the program. Read the input string and compute its length .
cin >> s; n = s.size();Initialize the arrays and .
memset(dp,0,sizeof(dp));
memset(pal,-1,sizeof(pal));Iterate over all substrings s_i \ldots s_{i + len} of the string in increasing order of their length . This is important because the value of dp[i][j] depends on the values for shorter substrings.
for (len = 1; len < n; len++)
for (i = 0; i + len < n; i++)
{The right boundary of the substring s_i \ldots s_{i + len} is j = i + len.
j = i + len;If the substring s_i \ldots s_j is a palindrome, then it is automatically also a superpalindrome.
if (IsPal(i,j))
{
dp[i][j] = 1;
continue;
}If the substring s_i \ldots s_j is not a palindrome, we try to represent it as a concatenation of two superpalindromes.
If s_i \ldots s_k and s_{k+1} \ldots s_j are superpalindromes, then s_i \ldots s_j is a superpalindrome as well.
for (k = i + 1; k < j - 1; k++)
if (dp[i][k] && dp[k + 1][j])
{
dp[i][j] = 1;
break;
}
}Count the number of superpalindromes. It is equal to the number of index pairs (i, j) for which dp[i][j] = 1.
res = 0;
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
res += dp[i][j];Print the answer.
printf("%d\n",res);Algorithm implementation – recursion
Declare the input string and arrays.
#define MAX 1010
string s;
int dp[MAX][MAX], pal[MAX][MAX];The function IsPal checks whether the substring s_i \ldots s_j is a palindrome. The substring s_i \ldots s_j is a palindrome if s_i = s_j and the substring s_{i + 1} \ldots s_{j - 1} is also a palindrome. The values of the function IsPal are stored in the cells of the two-dimensional array pal[i][j].
int IsPal(int i, int j)
{
if (i >= j) return pal[i][j] = 1;
if (pal[i][j] != -1) return pal[i][j];
return pal[i][j] = (s[i] == s[j]) && IsPal(i+1,j-1);
}The function f returns if the substring s_i \ldots s_j is a superpalindrome.
int f(int i, int j)
{A superpalindrome must contain more than one character.
if (i == j) return dp[i][j] = 0;If the value of f is already computed, return this value.
if (dp[i][j] != -1) return dp[i][j];If the substring s_i \ldots s_j~(i < j) is a palindrome, then it is also a superpalindrome.
if (IsPal(i,j)) return dp[i][j] = 1;If the substring s_i \ldots s_k~(i < k) is a palindrome and the substring s_{k+1} \ldots s_j~(k + 1 < j) is a superpalindrome, then the substring s_i \ldots s_j is a superpalindrome.
for (int k = i + 1; k < j - 1; k++)
if (IsPal(i,k) && f(k + 1,j)) return dp[i][j] = 1;If none of the conditions described above is satisfied, then the substring s_i \ldots s_j is not a superpalindrome.
return dp[i][j] = 0;
}The main part of the program. Read the input string and compute its length .
cin >> s; n = s.size();Initialize the arrays and .
memset(dp,-1,sizeof(dp));
memset(pal,-1,sizeof(pal));In the variable count the number of superpalindromes.
res = 0;
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
res += f(i,j);Print the answer.
cout << res << endl;Java implementation
import java.util.*;
public class Main
{
static String s;
static int dp[][], pal[][];
static int IsPal(int i, int j)
{
if (i >= j) return pal[i][j] = 1;
if (pal[i][j] != -1) return pal[i][j];
if (s.charAt(i) == s.charAt(j) && IsPal(i+1,j-1) == 1) pal[i][j] = 1;
else pal[i][j] = 0;
return pal[i][j];
}
static int f(int i, int j)
{
if (i == j) return dp[i][j] = 0;
if (dp[i][j] != -1) return dp[i][j];
if (IsPal(i,j) == 1) return dp[i][j] = 1;
for(int k = i + 1; k < j - 1; k++)
if(IsPal(i,k) == 1 && f(k + 1,j) == 1) return dp[i][j] = 1;
return dp[i][j] = 0;
}
public static void main(String[] args)
{
Scanner con = new Scanner(System.in);
s = con.nextLine();
int n = s.length();
dp = new int[n][n];
pal = new int[n][n];
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
dp[i][j] = -1;
pal[i][j] = -1;
}
int res = 0;
for(int i = 0; i < n; i++)
for(int j = i+1; j < n; j++)
res += f(i,j);
System.out.println(res);
con.close();
}
}