Codeforces Round #427 (Div. 2) D. Palindromic characteristics dp

来源:互联网 发布:阿里代销淘宝图片处理 编辑:程序博客网 时间:2024/05/21 21:41

题意

定义k-回文串为:
若一个字符串为回文串,则该字符串为1-回文串。
若一个字符串为回文串,且其左半部分(奇数长度则不包括中间字符)与右半部分均为k-1-回文串,则该串为k-回文串。
给出一个长度为n的字符串,问这个字符串的子串中有多少个k-回文串(k in [1..n])
n<=5000

分析

比赛的时候一看到题,下意识地以为这是道大字符串题,然后就满脑子的字符串操作。。。
一开始用hash,然后把hash值扔到map里面统计一波数量,然后用manachar求出本质不同的O(n)个回文串,每个分别用O(log)的复杂度去找其对应的k,最后记录答案。
结果T到死,挂了5次。。。

其实只要dp一下就好了。设f[i,j]表示s[i…j]这一段对应的k值是多少。注意到若一个串是k-回文串,则其一定是k-1-回文串。这样的话就可以直接递推了。
一开始用单hash来判回文串,结果被卡了。。。后面改成dp,s[i,j]是回文串当且仅当s[i+1,j-1]是回文串且s[i]==s[j]。

代码

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<map>using namespace std;typedef long long LL;const int N=5005;int n,ans[N],hash[N][N],f[N][N];char s[N];bool vis[N][N];int main(){    scanf("%s",s+1);    n=strlen(s+1);    for (int i=1;i<=n;i++) vis[i][i]=vis[i][i-1]=1;    for (int l=1;l<n;l++)        for (int i=1;i+l<=n;i++)        {            int j=i+l;            vis[i][j]=(s[i]==s[j]&&vis[i+1][j-1]);        }    for (int i=1;i<=n;i++) f[i][i]=1;    for (int l=1;l<n;l++)        for (int i=1;i+l<=n;i++)        {            int j=i+l;            if (!vis[i][j]) continue;            int len=(j-i+1)/2;            f[i][j]=f[i][i+len-1]+1;        }    for (int i=1;i<=n;i++)        for (int j=i;j<=n;j++)            ans[f[i][j]]++;    for (int i=n;i>=1;i--) ans[i]+=ans[i+1];    for (int i=1;i<=n;i++) printf("%d ",ans[i]);    return 0;}
阅读全文
1 0
原创粉丝点击