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);
}
posted @ 2020-01-30 14:12  Shiina_Mashiro  阅读(108)  评论(0编辑  收藏  举报