首先可以用递推的思想来考虑,如果已经求得了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;
}