BZOJ3620 似乎在梦中见过的样子

Link
枚举左端点(i),然后计算有多少右端点满足条件。
我们可以先跑出(s_{i,n})的KMP数组,然后处理出(pos)表示(s_{i,j})的最短的并且长度(ge k)的border的右端点,然后再看是否长度(lelfloorfrac{j-i}2 floor)

#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);
}
原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12242697.html