Codeforces 835D Round #427 Div2D :回文串DP

题意:定义1阶回文串:从左到右读等于从右到左读。k(k>=2)阶回文串为:本身是1阶回文串,且左半边和右半边都是k-1阶回文串。左半边:[ l , l+(r-l+1)/2-1 ];右半边:[ r-(r-l+1)/2+1 , r ]。求阶数为 1 到 len 的回文字串的个数。

题解:子问题!子问题!子问题!k阶回文串的第一个定义:自身是回文串,这个等价于s[ l+1 ][ r-1 ]是一个回文串 && s[ l ] == s[ r ]。第二个条件:左半边和右半边都是 k-1 阶回文串,显然当[ l .. r ]字串是一个回文串的时候,左右半边的阶数是相同的。那么我们可以按照长度来进行 dp ,这样保证在算[ l .. r ]最大的阶数的时候,左右半串都已经算完了。最后一个问题:一个k阶回文串,按照定义,他也是k-1阶,k-2阶……1阶回文串,因此我们只需要确定字串的最大阶就可以了。

dp[ l ][ r ]表示s[ l .. r ]的最大阶数。cot[ x ]表示 x阶串总共有cot[ x ]个。代码简单易懂,稍微注意一下初始条件就没问题了。

Code:

#include<bits/stdc++.h>
using namespace std;
const int MAX = 5050;
char s[MAX];
int dp[MAX][MAX];
int cot[MAX];
int ans[MAX];
int main(){
	scanf("%s",s);
	int len = strlen (s);
	for (int i=0;i<=len;i++){
		dp[i][i] = 1;
		dp[i][i-1] = 1;
	}
	cot[1] = len;
	for (int k=2;k<=len;k++){
		for (int l = 0;l<=len-k;l++){
			int r = l+k-1;
			if (s[l]==s[r]&&dp[l+1][r-1]){
				dp[l][r] = dp[l][l-1+((r-l+1)>>1)]+1;
//				printf("dp[%d][%d]:%d\n",l,r,dp[l][r]);
				cot[dp[l][r]]++;
			}
		}
	}
	int sum =0;
	for (int i=len;i>=1;i--){
		sum+=cot[i];
		ans[i] = sum;
	}
	for (int i=1;i<=len;i++){
		printf("%d ",ans[i]);
	}
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值