P5112 FZOUTSY

P5112 FZOUTSY

建个后缀自动机,当然这里得反着建
找到最小的大于k的子串,相当于最小满足的子串,\(endpos\)最大,然后沿\(parents\)边都染成同一色
同色的都满足后缀的最长公共前缀满足大于k,接下来就是莫队在树上跑

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn=10000000;
inline LL Read(){
    LL x=0,f=1; char c=getchar();
    while(c<'0'||c>'9'){
        if(c=='-') f=-1; c=getchar();
    }
    while(c>='0'&&c<='9'){
        x=(x<<3)+(x<<1)+c-'0'; c=getchar();
    }return x*f;
}
LL n,m,K,last,nod,num,tot,size,pieces;
LL col[maxn],ans[maxn],len[maxn],fail[maxn],son[maxn][7],head[maxn];
LL belong[maxn],cnt[maxn];
LL ch[500];
char s[maxn];
inline void Init(){
    last=n+1,nod=n+1;
    for(LL i=1;i<=n;++i)
        len[i]=i;
}
inline void Insert(LL c,LL now){
    LL p=last;
    last=now;
    while(p&&!son[p][c])
        son[p][c]=now,
        p=fail[p];
    if(!p)
        fail[now]=n+1;
    else{
        LL q=son[p][c];
        if(len[q]==len[p]+1)
            fail[now]=q;
        else{
            LL nq=++nod;
            len[nq]=len[p]+1;
            memcpy(son[nq],son[q],sizeof(son[q]));
            fail[nq]=fail[q], fail[q]=fail[now]=nq;
            while(p&&son[p][c]==q)
                son[p][c]=nq,
                p=fail[p];
        }
    }
}
struct code{
    LL to,next;
}dis[maxn];
inline void Add(LL u,LL v){
    dis[++num]=(code){v,head[u]},head[u]=num;
}
inline void Build(){
    for(LL i=1;i<=nod;++i)
        Add(fail[i],i);
}
void Dfs(LL u,LL co){
    if(u<=n)
        col[u]=co;
    if(co)
        for(LL i=head[u];i;i=dis[i].next)
            Dfs(dis[i].to,co);
    else
        for(LL i=head[u];i;i=dis[i].next){
        	LL v=dis[i].to;
            if(len[v]>=K)
                Dfs(v,++tot);
            else
                Dfs(v,0);
        }
}
struct node{
    LL l,r,id;
}q[maxn];
inline bool cmp(node x,node y){
    return (belong[x.l]^belong[y.l])?
            belong[x.l]<belong[y.l]:
            	(belong[x.l]&1)?
            	    x.r<y.r:x.r>y.r;
}
LL sum;
inline void Inc(LL x){
    x=col[x];
    if(x)
        sum+=cnt[x],cnt[x]++;
}
inline void Del(LL x){
    x=col[x];
    if(x)
        cnt[x]--,
        sum-=cnt[x];
}
int main(){
    ch['y']=0,ch['u']=1,ch['z']=2,ch['s']=3,ch['o']=4,ch['f']=5,ch['t']=6;
    n=Read(),m=Read(),K=Read();
    scanf(" %s",s+1);
    Init();
    for(LL i=n,j=1;i>=1;--i,++j)
        Insert(ch[s[i]],j);
    Build();
    Dfs(n+1,(K==0));
    for(LL i=1;i<=(n/2);++i)
        swap(col[i],col[n-i+1]);
    for(LL i=1;i<=m;++i){
        LL l=Read(),r=Read();
        q[i]=(node){l,r,i};
    }
    size=ceil((double)n/sqrt(m));
    pieces=n/size;
    for(LL i=1;i<=pieces;++i)
        for(LL j=(i-1)*pieces+1;j<=i*pieces;++j)
            belong[j]=i;
    sort(q+1,q+1+m,cmp);
    LL l=1,r=0;
    for(LL i=1;i<=m;++i){
        LL ql=q[i].l,qr=q[i].r,x;
        while(l<ql)
            Del(l++);
        while(l>ql)
            Inc(--l);
        while(r<qr)
            Inc(++r);
        while(r>qr)
            Del(r--);
        ans[q[i].id]=sum;
    }
    for(LL i=1;i<=m;++i)
        printf("%lld\n",ans[i]);
    return 0;
}
posted @ 2018-12-30 23:47  y2823774827y  阅读(140)  评论(0编辑  收藏  举报