CF835 D DP

所有所有阶回文串的个数。对于一个k阶回文串,定义为:它的左右两侧相同且是k-1阶回文串

显然高阶回文串由低阶构成,那么枚举长度,从左到右遍历,dp[l][r]代表从l到r串最大的阶数,cnt[i]记录i阶的个数,显然转移为dp[l][r]=dp[l][r-len/2-1] + 1

/** @Date    : 2017-08-12 11:24:44
  * @FileName: D DP.cpp
  * @Platform: Windows
  * @Author  : Lweleth (SoungEarlf@gmail.com)
  * @Link    : https://github.com/
  * @Version : $Id$
  */
#include <bits/stdc++.h>
#define LL long long
#define PII pair<int ,int>
#define MP(x, y) make_pair((x),(y))
#define fi first
#define se second
#define PB(x) push_back((x))
#define MMG(x) memset((x), -1,sizeof(x))
#define MMF(x) memset((x),0,sizeof(x))
#define MMI(x) memset((x), INF, sizeof(x))
using namespace std;

const int INF = 0x3f3f3f3f;
const int N = 1e5+20;
const double eps = 1e-8;

char s[N];
int dp[5010][5010];
int cnt[5010];

int main()
{
	while(~scanf("%s", s + 1))
	{
		MMF(dp);
		MMF(cnt);
		int len = strlen(s + 1);
		for(int i = 1; i <= len; i++)
		{
			dp[i][i] = 1;
			if(s[i] == s[i + 1])
				dp[i][i + 1] = 2, cnt[2]++, cnt[1]++;
			cnt[1]++;
		}

		for(int k = 3; k <= len; k++)
		{
			for(int l = 1; l + k - 1 <= len; l++)
			{
				int r = l + k - 1;
				if(s[l] != s[r] || !dp[l + 1][r - 1])
					continue;
				int mid = (l + r) >> 1;
				dp[l][r] = dp[l][l + k/2 - 1] + 1;//边界
				for(int i = 1; i <= dp[l][r]; i++)
					cnt[i]++;
			}
		}

		for(int i = 1; i <= len; i++)
			printf("%d%s", cnt[i], i==len?"
":" ");
	}
    return 0;
}
原文地址:https://www.cnblogs.com/Yumesenya/p/7449773.html