BZOJ3620: 似乎在梦中见过的样子
【传送门:BZOJ3620】
简要题意:
给出一个字符串和一个正整数k,判断有多少个子串为A+B+A的形式,如:aabaa(aa+b+aa),cbaccba(cba+c+cba)
注意不同位置但A,B相同算不同的子串,相同位置但A,B不同算相同子串
要求在len(A)>=k,len(B)>=1的情况下的子串数
题解:
听旁边的Rose_max说O(n2)可以过??据说什么数据水????
直接敲,枚举子串开头,然后跑KMP,cnt[i]表示以i为结尾的,在开头能够找到匹配字符串>=k的情况下的最小长度,然后判断cnt是否满足就好了嘛
参考代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> using namespace std; int p[21000],bak[21000]; char st[21000]; int main() { scanf("%s",st+1);int n=strlen(st+1); int k; scanf("%d",&k); int ans=0; bak[0]=999999999; for(int t=1;t<=n;t++) { p[t]=t-1;bak[t]=999999999; for(int i=t+1;i<=n;i++) { int j=p[i-1]; while(st[j+1]!=st[i]&&j!=(t-1)) j=p[j]; if(st[j+1]==st[i]) j++; p[i]=j; bak[i]=bak[j]; if(p[i]-t+1>=k) bak[i]=min(bak[i],p[i]-t+1); if(bak[i]>=k&&2*bak[i]<=i-t) ans++; } } printf("%d\n",ans); return 0; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚