BZOJ3620 似乎在梦中见过的样子(kmp)
不是很懂为什么数据范围要开的这么诡异,想到正解都不敢写。用类似NOI2014动物园的方法,对每个后缀求出类似next的数组即可。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; int read() { int x=0,f=1;char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();} while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 15010 int n,m,nxt[N],exnxt[N],ans=0; char s[N]; int main() { #ifndef ONLINE_JUDGE freopen("bzoj3620.in","r",stdin); freopen("bzoj3620.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif scanf("%s",s+1);n=strlen(s+1);m=read(); for (int i=1;i<n;i++) { nxt[i]=exnxt[i]=i-1;nxt[i+1]=s[i]==s[i+1]?i:i-1,exnxt[i+1]=i-1; for (int j=i+2;j<=n;j++) { int k=nxt[j-1]; while (k>=i&&s[k+1]!=s[j]) k=nxt[k]; if (s[k+1]==s[j]) nxt[j]=k+1;else nxt[j]=k; k=exnxt[j-1]; while (k>=i&&(s[k+1]!=s[j]||(k+2-i<<1)>=j-i+1)) k=nxt[k]; if (s[k+1]==s[j]) exnxt[j]=k+1;else exnxt[j]=k; if (exnxt[j]-i+1>=m) ans++; } } cout<<ans; return 0; }