这道题,和同学一起作比赛。刚做的时候就感觉是KMP,然后各种找方法,两个小时过去了还是没有思路。之后看大牛的题解才知道这个是动态KMP,真是水到家了。。。
题意:给你两个字符串 r和s, 开始 r=s ,然后把r删掉一段后缀(也可以不删),接着r+=s ;重复多次。
解法:动态KMP,T是原串,P是匹配串,last是标记。初始时使T[0]=P[0],接着进行匹配。如果不能完全匹配,就把last+1到当前位置i的串加到P的后面计算匹配串的适配指针,继续匹配。如果完全匹配了就把last更新到当前位置。如此往复。最后答案就是 m(匹配串长度) + n(原串长度)-last(标记)-1 -> m+n-last-1
Trick:就是必须自己手写KMP,对于我这每次都是copy模板的人好痛苦。
代码:
#include<iostream>
#include<string>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn = 100000 + 10;
int main()
{
//freopen("in.txt","r",stdin);
char T[maxn], P[maxn];
int kase = 1, f[maxn];
while(~scanf("%s", T))
{
int last = 0, m = 1, j = 0, n = strlen(T);
memset(P, 0, sizeof P);
P[0] = T[0];
f[0] = f[1] = 0;
for(int i = 1 ; i < n ; ++ i)
{
while(j&&T[i]!=P[j]) j = f[j];
if(T[i]==P[j]) ++j;
if(!j)
{
int t = f[m];
for(int k = last+1 ; k <= i ; ++ k)
{
P[m++] = T[k];
while(t&&P[m-1]!=P[t]) t = f[t];
f[m] = P[m-1]==P[t]?t+1:0;
}
j = m;
}
if(j==m) last = i;
}
printf("Case %d: %d\n", kase++, m + n - last - 1);
}
return 0;
}