BZOJ 3620 似乎在梦中见过的样子

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);
}

猜你喜欢

转载自www.cnblogs.com/cjoierShiina-Mashiro/p/12242697.html