Fork me on GitHub

UVA10617-Again Palindrome

UVA10617-Again Palindrome

题意

T组数据,每次给出一个字符串s,问它有多少个回文序列

题解

根据子串的长度,如果已知长度为len-1的字符串中所含回文子序列的个数,那么可以推出长度为len的字符串中回文子序列的个数。
dp[l][r]表示在区间[l,r]中的回文子序列数,该字符串长度为r-l+1。那么如果\(s[l] \neq s[r]\),dp[l][r]=dp[l][r-1]+dp[l+1][r]-dp[l+1][r-1]。如果\(s[l]=s[r]\),dp[l][r]=dp[l][r-1]+dp[l+1][r]-dp[l+1][r-1]+1(s[l]和s[r]组成的回文子序列)+dp[l+1][r-1](以s[l]和s[r]作为两端的回文子序列),化简为dp[l][r]=dp[l][r-1]+dp[l+1][r]+1。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=65;
char s[N];
ll dp[N][N];
ll ans;
int t,n;

int main(){
	scanf("%d",&t);
	while(t--){
		scanf("%s",s+1);
		n=strlen(s+1);
		for(int i=1;i<=n;i++) dp[i][i]=1;
		for(int len=2;len<=n;len++){
			for(int l=1;l<=n;l++){
				int r=l+len-1;
				if(s[l]==s[r]){
					dp[l][r]=dp[l][r-1]+dp[l+1][r]+1;
				}else{
					dp[l][r]=dp[l][r-1]+dp[l+1][r];
					if(l+1<=r-1) dp[l][r]-=dp[l+1][r-1];
				}
			}
		}
		printf("%lld\n",dp[1][n]);
	}
	return 0;
}
posted @ 2020-03-19 15:32  qjy_73  阅读(120)  评论(0)    收藏  举报