字符串(AC自动机+fail tree)
题目描述:
题解:
a[i] 实际就是字符串 i 在总集合中出现的次数,很自然地想到fail tree
注意:注释中的那段代码是不能用的
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<queue> using namespace std; typedef long long ll; const int N=2000010; struct Edge{int v,nxt;}edge[N]; int head[N],cnt; int ch[N][26],fail[N],word[N],num; int st[N],ed[N],tot; int m,l,len[N],bg[N],que,work[N]; ll c[N],mask,ans,val[N],opt[N]; char s[N],str[N]; void add_edge(int u,int v){ edge[++cnt].v=v; edge[cnt].nxt=head[u]; head[u]=cnt; } void insert(char *s,int id){ int now=0; for(int i=0;i<len[id];i++){ int x=s[i]-'a'; if(!ch[now][x]) ch[now][x]=++num; now=ch[now][x]; } word[id]=now; } void get_fail(){ queue<int> q; for(int i=0;i<26;i++){ if(ch[0][i]) q.push(ch[0][i]); } while(!q.empty()){ int now=q.front(); q.pop(); for(int i=0;i<26;i++){ if(ch[now][i]){ fail[ch[now][i]]=ch[fail[now]][i]; q.push(ch[now][i]); } else ch[now][i]=ch[fail[now]][i]; } } } void dfs(int u){ st[u]=++tot; for(int i=head[u];i;i=edge[i].nxt) dfs(edge[i].v); ed[u]=tot; } void build_fail_tree(){ for(int i=1;i<=num;i++) add_edge(fail[i],i); dfs(0); } inline int lowbit(int x){return x&(-x);} void add(int x,int d){ for(int i=x;i<=tot;i+=lowbit(i)) c[i]+=d; } ll getsum(int x){ ll sum=0; for(int i=x;i>=1;i-=lowbit(i)) sum+=c[i]; return sum; } void query(int l,int r){ que++; int now=0; for(int i=l;i<=r;i++){ now=ch[now][s[i]-'a']; if(work[now]==que)//子串在s中已经出现过 ans+=val[now]; else{ work[now]=que; //val[now]=getsum(ed[now])-getsum(st[now]-1); val[now]=getsum(st[now]); ans+=val[now]; } } } int main(){ scanf("%d",&m); for(int i=1;i<=m;i++){ scanf("%lld%s",&opt[i],str); len[i]=strlen(str); bg[i]=l+1; insert(str,i); for(int j=0;j<len[i];j++) s[++l]=str[j]; } get_fail(); build_fail_tree(); for(int i=1;i<=m;i++){ opt[i]^=mask; if(opt[i]==1){ add(st[word[i]],1); add(ed[word[i]]+1,-1); } //add(st[word[i]],1); else if(opt[i]==2){ add(st[word[i]],-1); add(ed[word[i]]+1,1); } //add(st[word[i]],-1); else if(opt[i]==3){ ans=0; query(bg[i],bg[i]+len[i]-1); printf("%lld\n",ans); mask^=labs(ans); } } return 0; }