给一个串s,找最小的一个串t,使得原串是这个最小串的前缀+前缀+..(很多很多的前缀)+这个最小串构成。
很难思考的题目。
可以想到一种思路:能用短的匹配,就不用长的。
利用KMP,当不能匹配的时候,就从上一个匹配完成的位置开始把剩下的那段加到t中。
为什么要找上次匹配完成的位置last呢?
因为这样做能保证t是一个最短的能满足构成s[0..i]的串。
由于最后需要一个完整的t,因此答案是找到最后一次完整匹配的开头位置(last-m)到串尾的长度。
很难思考的题目。
可以想到一种思路:能用短的匹配,就不用长的。
利用KMP,当不能匹配的时候,就从上一个匹配完成的位置开始把剩下的那段加到t中。
为什么要找上次匹配完成的位置last呢?
因为这样做能保证t是一个最短的能满足构成s[0..i]的串。
由于最后需要一个完整的t,因此答案是找到最后一次完整匹配的开头位置(last-m)到串尾的长度。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define NN 100010
char s[NN],t[NN];
int next[NN];
int kmp(){
int l=strlen(s);
int i=0,j=-1,k,y=-1;
int m=0,last=0;
next[i]=j;
while(i<l){
if (j==-1){
for(k=last;k<=i;++k){
t[m]=s[k];
while(y!=-1&&t[y]!=t[m]) y=next[y];
y++;m++;next[m]=y;
}
j=m;
i++;
}
else if(s[i]==t[j]){i++;j++;}
else j=next[j];
if (j>=m) {last=i;j=0;}
}
return l-(last-m);
}
int main(){
//freopen("4468in.txt","r",stdin);
int ans,cas;
cas=0;
while(gets(s)){
cas++;
ans=kmp();
printf("Case %d: %d\n",cas,ans);
}
return 0;
}