回文子序列
Problem statement:
问题陈述:
Given a string str, find total number of possible palindromic sub-sequences. A sub-sequence does not need to be consecutive, but for any xixj i<j must be valid in the parent string too. Like "icl" is a subsequence of "includehelp" while "ple" is not.
给定字符串str ,找到可能的回文子序列的总数。 子序列不必是连续的,但是对于任何x i x j i <j在父字符串中也必须有效。 像“ icl”一样,是“ includehelp”的子序列,而“ ple”则不是。
Input:
输入:
The first line of input contains an integer T, denoting the no of test cases then T test cases follow. Each test case contains a string str.
输入的第一行包含一个整数T ,表示测试用例的数量,然后是T个测试用例。 每个测试用例都包含一个字符串str 。
Output:
输出:
For each test case output will be an integer denoting the total count of palindromic subsequence which could be formed from the string str.
对于每个测试用例,输出将是一个整数,表示回文子序列的总数,该总数可以由字符串str形成。
Constraints:
限制条件:
1 <= T <= 100
1 <= length of string str <= 300
Example:
例:
Input:
Test case: 2
First test case:
Input string:
"aaaa"
Output:
Total count of palindromic subsequences is: 15
Second test case:
Input string:
"abaaba"
Output:
Total count of palindromic subsequences is: 31
Explanation:
说明:
Test case 1:
测试用例1:
Input: "aaaa"
输入:“ aaaa”
The valid palindromic subsequences are shown below,
有效回文子序列如下所示,
Marked cells are character taken in subsequence:
标记的单元格是子序列中的字符:
Count=1
计数= 1
Count=2
计数= 2
Count=3
计数= 3
Count=4
计数= 4
Count=5
计数= 5
Count=6
计数= 6
Count=7
计数= 7
Count=8
计数= 8
Count=9
计数= 9
Count=10
数= 10
Count=11
数= 11
So on...
Total 15 palindromic sub-sequences
Actually in this case since all the character is same each and every subsequence is palindrome here.
For the second test case
Few sub-sequences can be
"a"
"b"
"a"
"aba"
So on
Total 31 such palindromic subsequences
等等...
总共15个回文子序列
实际上,在这种情况下,由于所有字符都是相同的,每个子序列在这里都是回文。
对于第二个测试用例
很少有子序列可以是
“一个”
“ b”
“一个”
“阿巴”
依此类推
总共31个这样的回文序列
Solution approach
解决方法
This can be solved by using DP bottom up approach,
这可以通过使用DP自下而上的方法来解决,
Initialize dp[n][n] where n be the string length to 0
初始化dp [n] [n] ,其中n为0的字符串长度
Fill up the base case, Base case is that each single character is a palindrome itself. And for length of two, i.e, if adjacent characters are found to be equal then dp[i][i+1]=3, else if characters are different then dp[i][i+1]=2
填满基本情况,基本情况是每个单个字符本身都是回文。 对于两个长度,即,如果发现相邻字符相等,则dp [i] [i + 1] = 3 ;否则,如果字符不同,则dp [i] [i + 1] = 2
To understand this lets think of a string like "acaa"
要理解这一点,可以考虑一个字符串,例如“ acaa”
Here
这里
dp[0][1]=2 because there's only two palindrome possible because of "a" and "c".
dp [0] [1] = 2是因为“ a”和“ c”仅可能存在两个回文。
Whereas for
鉴于
dp[2][3] value will be 3 as possible subsequences are "a", "a", "aa".
dp [2] [3]的值将为3,因为可能的子序列为“ a”,“ a”,“ aa”。
for i=0 to n // for single length characters dp[i][i]=1; if(i==n-1) break; if(s[i]==s[i+1]) dp[i][i+1]=3; else dp[i][i+1]=2; end for
Compute for higher lengths,
计算更长的长度,
for len=3 to n for start=0 to n-len int end=start+len-1; // start and end is matching if(s[end]==s[start]) // 1+subsequence from semaining part dp[start][end]=1+dp[start+1][end]+dp[start][end-1]; else dp[start][end]=dp[start+1][end]+dp[start][end-1]-dp[start+1][end-1]; end if end for end for
Final result is stored in dp[0][n-1];
最终结果存储在dp [0] [n-1]中;
So for higher lengths if starting and ending index is the same then we recur for the remaining characters, since we have the sub-problem result stored so we computed that. In case start and end index character are different then we have added dp[start+1][end] and dp[start][end-1] that's similar to recur for leaving starting index and recur for leaving end index. But it would compute dp[start+1][end-1] twice and that why we have deducted that.
因此,对于更大的长度,如果开始索引和结束索引相同,那么我们将重复其余字符,因为我们存储了子问题结果,因此我们对其进行了计算。 如果起始索引和终止索引的字符不同,则我们添加了dp [start + 1] [end]和dp [start] [end-1] ,类似于recur离开起始索引和recur离开结束索引。 但是它将两次计算dp [start + 1] [end-1] ,这就是为什么我们要减去它。
For proper understanding you can compute the table by hand for the string "aaaa" to understand how it's working.
为了正确理解,您可以手动计算字符串“ aaaa”的表以了解其工作方式。
C++ Implementation:
C ++实现:
#include <bits/stdc++.h>
using namespace std;
int countPS(string s)
{
int n = s.length();
int dp[n][n];
memset(dp, 0, sizeof(dp));
for (int i = 0; i < n; i++) {
dp[i][i] = 1;
if (i == n - 1)
break;
if (s[i] == s[i + 1])
dp[i][i + 1] = 3;
else
dp[i][i + 1] = 2;
}
for (int len = 3; len <= n; len++) {
for (int start = 0; start <= n - len; start++) {
int end = start + len - 1;
if (s[end] == s[start]) {
dp[start][end] = 1 + dp[start + 1][end] + dp[start][end - 1];
}
else {
dp[start][end] = dp[start + 1][end] + dp[start][end - 1] - dp[start + 1][end - 1];
}
}
}
return dp[0][n - 1];
}
int main()
{
int t;
cout << "Enter number of testcases\n";
cin >> t;
while (t--) {
string str;
cout << "Enter the input string\n";
cin >> str;
cout << "Total Number of palindromic Subsequences are: " << countPS(str) << endl;
}
return 0;
}
Output:
输出:
Enter number of testcases
2
Enter the input string
aaaa
Total Number of palindromic Subsequences are: 15
Enter the input string
abaaba
Total Number of palindromic Subsequences are: 31
翻译自: https://www.includehelp.com/icp/count-total-number-of-palindromic-subsequences.aspx
回文子序列