BZOJ3620 似乎在梦中见过的样子
Link
枚举左端点\(i\),然后计算有多少右端点满足条件。
我们可以先跑出\(s_{i,n}\)的KMP数组,然后处理出\(pos\)表示\(s_{i,j}\)的最短的并且长度\(\ge k\)的border的右端点,然后再看是否长度\(\le\lfloor\frac{j-i}2\rfloor\)。
#include<cstdio>
#include<cstring>
const int N=15007;
char s[N];int next[N],pos[N];
int main()
{
int n,l,ans=0;
scanf("%s%d",s+1,&l),n=strlen(s+1);
for(int i=1;i<=n;++i)
{
next[i]=i-1,pos[i]=i;
for(int j=i+1,k=i-1;j<=n;++j)
{
while(k>=i&&s[k+1]^s[j]) k=next[k];
if(s[k+1]==s[j]) ++k;
next[j]=k,pos[j]=k<i+l-1? j:pos[k];
if(pos[j]<(i+j)>>1) ++ans;
}
}
printf("%d", ans);
}