bzoj3620似乎在梦中见过的样子

bzoj3620似乎在梦中见过的样子

题意:

给出一个字符串,要求求出形如A+B+A的子串数量,且lenA≥k,lenB≥1。字符串长度≤15000,k≤100,所以字符长度为小写字母。

题解:

第一次写kmp的题QAQ~这题利用的是fail函数的性质:若字符串s在位置x的fail函数f[x]不为0,则prefix(s+1,s+x)的长度为f[x]的前缀和长度为f[x]的后缀相同。因此枚举每个后缀为为j,对这个后缀做kmp,再递推一个令f[i]-j+1≥k且最小的f[i]为last[x](f[i]表示i=x; while(i>=后缀位)i=f[i]得到的所有f[i]),若last[x]-j小于等于(x-j)/2则子串(j,x)合法。讲的很乱,具体看代码。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <queue>
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define INF 0x3fffffff
 7 using namespace std;
 8 
 9 char s[15100]; int l,k,next[15100],last[15100],ans;
10 int main(){
11     //freopen("in.txt","r",stdin);
12     scanf("%s",s+1); l=strlen(s+1); scanf("%d",&k); ans=0;
13     inc(i,1,l){
14         next[i]=i-1; last[i]=INF;
15         inc(ii,i+1,l){
16             int j=next[ii-1]; while(j>=i&&s[ii]!=s[j+1])j=next[j];
17             if(s[ii]==s[j+1])next[ii]=j+1;else next[ii]=j;
18             if(next[ii]-i+1<k)last[ii]=INF;else{
19                 last[ii]=min(last[next[ii]],next[ii]);
20                 if(last[ii]-i+1<=(ii-i)>>1)ans++;//,printf("%d %d\n",i,ii);
21             }
22         }
23     }
24     printf("%d",ans); return 0;
25 }

 

20160609

posted @ 2016-08-16 22:52  YuanZiming  阅读(673)  评论(0编辑  收藏  举报