hdu 4468 spy kmp+dp

来源:互联网 发布:休闲网游 知乎 编辑:程序博客网 时间:2024/04/27 16:40

首先可以用递推的思想来考虑,如果已经求得了dp[i]的答案,怎么得到dp[i+1]的答案。这个dp值是不考虑最后一个字符需要完整的。

只需要判断所有以i+1个字符为结尾的串中有没有一个是现在的模式串的前缀,有的话证明dp[i]的值就是dp[i+1]的值。

否则这个i+1号字符及它之前的还未匹配的串就一定要加入到模式串中。

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn=1e5+9;char a[maxn],ans[maxn];int next[maxn];int main(){    freopen("in.txt","r",stdin);    int cas=0;    while(scanf("%s",a+1)!=EOF)    {        memset(ans,0,sizeof(ans));        memset(next,0,sizeof(next));        int n=strlen(a+1),top=0,last=0,pre=0;        for(int i=1,j;i<=n;i++)        {            j=pre;            while(j&&(a[i]!=ans[j+1])) j=next[j];            if(a[i]!=ans[j+1])            {                for(int k=last+1,t;k<=i;k++)                {                    ans[++top]=a[k];                    t=next[top-1];                    while(t&&(a[k]!=ans[t+1])) t=next[t];                    next[top]=t+(a[k]==ans[t+1]);                    if(top==1) next[top]=0;                }                last=i;                int t=next[top-1];                while(t&&ans[top]!=ans[t]) t=next[t];                pre=t+(ans[top]==ans[t]);            }            else            {                pre=j+1;                if(j+1==top) last=i;            }        }        memset(a,0,sizeof(a));        printf("Case %d: %d\n",++cas,top+n-last);    }    return 0;}


原创粉丝点击