【51nod1006】simple KMP
原题意看的挺迷糊的,后来看了http://blog.csdn.net/YxuanwKeith/article/details/52351335大爷的题意感觉清楚的多……
做法也非常显然了,用树剖维护后缀自动机的parent树。
修改操作看成对每一个状态的right集合全都访问次数+1
询问同理。
然后我忘了更新爬后缀树时候的新状态调了挺久的。。。。。
因为这么傻逼的错误还能过样例。。。。。
#include<bits/stdc++.h> const int N=2e5+10; const int yql=1e9+7; using namespace std; int n,rt,tot=0,head[N],cnt; int size[N],wson[N],tpos[N],top[N],fa[N],d[N],len,pre[N]; char s[N]; struct Edge{int u,v,next;}G[N<<1]; struct Suffix_AutoMaton{ int ch[N<<1][26],fa[N<<1],l[N<<1],cnt,last; inline void init(){cnt=1;last=1;} inline void ins(int c){ int p=last,np=++cnt;last=np;l[np]=l[p]+1; for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np; if(!p)fa[np]=1; else{ int q=ch[p][c]; if(l[p]+1==l[q])fa[np]=q; else{ int nq=++cnt;l[nq]=l[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); fa[nq]=fa[q]; fa[np]=fa[q]=nq; for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq; } } } }sam; inline void addedge(int u,int v){ G[++tot].u=u;G[tot].v=v;G[tot].next=head[u];head[u]=tot; G[++tot].u=v;G[tot].v=u;G[tot].next=head[v];head[v]=tot; } inline void dfs1(int u,int f){ size[u]=1; for(int i=head[u];i;i=G[i].next){ int v=G[i].v;if(v==f)continue; fa[v]=u;d[v]=d[u]+1; dfs1(v,u); size[u]+=size[v]; if(size[v]>size[wson[u]])wson[u]=v; } } inline void dfs2(int u,int tp){ tpos[u]=++cnt;pre[cnt]=u;top[u]=tp; if(wson[u])dfs2(wson[u],tp); for(int i=head[u];i;i=G[i].next){ int v=G[i].v; if(v==fa[u]||v==wson[u])continue; dfs2(v,v); } } struct Segment_Tree{ #define lson (o<<1) #define rson (o<<1|1) int sumv[N<<2],size[N<<2],addv[N<<2]; inline void pushup(int o){sumv[o]=(sumv[lson]+sumv[rson])%yql;} inline void pushdown(int o,int l,int r){ if(!addv[o])return; addv[lson]+=addv[o];addv[rson]+=addv[o]; sumv[lson]=(sumv[lson]+1LL*size[lson]*addv[o]%yql)%yql; sumv[rson]=(sumv[rson]+1LL*size[rson]*addv[o]%yql)%yql; addv[o]=0; } inline void build(int o,int l,int r){ if(l==r){size[o]=sam.l[pre[l]]-sam.l[sam.fa[pre[l]]];return;} int mid=(l+r)>>1; build(lson,l,mid);build(rson,mid+1,r); size[o]=(size[lson]+size[rson])%yql; } inline int querysum(int o,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return sumv[o]; int mid=(l+r)>>1,ans=0; pushdown(o,l,r); if(ql<=mid)ans=(ans+querysum(lson,l,mid,ql,qr))%yql; if(qr>mid)ans=(ans+querysum(rson,mid+1,r,ql,qr))%yql; return ans; } inline void optadd(int o,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){addv[o]+=1;if(addv[o]>yql)addv[o]-=yql;sumv[o]=(sumv[o]+size[o])%yql;return;} int mid=(l+r)>>1;pushdown(o,l,r); if(ql<=mid)optadd(lson,l,mid,ql,qr); if(qr>mid)optadd(rson,mid+1,r,ql,qr); pushup(o); } }T; int main(){ scanf("%d",&n); scanf("%s",s+1);sam.init(); for(int i=1;i<=n;i++)sam.ins(s[i]-'a'); for(int i=1;i<=sam.cnt;i++)addedge(sam.fa[i],i); dfs1(1,0);dfs2(1,1);T.build(1,1,sam.cnt); int p=1,ans=0,cur=0; for(int i=1;i<=n;i++){ int c=s[i]-'a';int u=sam.ch[p][c]; for(int j=u;j;j=fa[top[j]])cur=(cur+T.querysum(1,1,sam.cnt,tpos[top[j]],tpos[j]))%yql; ans=(ans+cur)%yql;printf("%d\n",ans); for(int j=u;j;j=fa[top[j]])T.optadd(1,1,sam.cnt,tpos[top[j]],tpos[j]); p=u; } }
zzq wc-ctsc-apio-NOI Au;yql精通多项式;zyz精通女装;由乃精通数据结构;孔老师是毒奶大师;我没有学上:我们都有光明的前途。