【bzoj3620】似乎在梦中见过的样子
枚举左端点,对于每个右端点处理出以右端点为结尾最大长度使得从左端点开始的前缀等于以右端点结束的后缀,即next数组
然后一直往前跳,直到长度小于子串长度的一半为止。
#include<algorithm> #include<iostream> #include<cstdlib> #include<cstring> #include<cstdio> #include<cmath> using namespace std; typedef long long LL; #define N 15010 char s[N]; int m,ans,k; int f[N],g[N]; int main() { scanf("%s",s+1); int n=strlen(s+1); scanf("%d",&m); for (int k,i=1;i<=n-(m<<1);i++) { f[i]=k=i-1; g[i]=i; for (int j=i+1;j<=n;j++) { while (k!=i-1 && s[j]!=s[k+1]) k=f[k]; if (s[j]==s[k+1]) k++; f[j]=k; g[j]=(k<i+m-1) ? j : g[k]; if (g[j]<((i+j)>>1)) ans++; } } printf("%d",ans); return 0; }