【bzoj2434】: [Noi2011]阿狸的打字机 字符串-AC自动机-BIT
x串在y串上的匹配次数就是y在自动机所有节点上能够通过fail走到x最后一个节点的个数
(就是y串任意一个前缀的后缀能匹配到x的个数)和【bzoj3172】: [Tjoi2013]单词差不多
把fail指针反向就是x的子树的和 用dfs序+BIT就可以维护了
如果把y串一个个走自动机显然会TLE
但是如果按照打字顺序模拟'a'-'z' 在trie上前进一格单点+1 'B'在trie上后退一格单点-1
那么显然可以得到所有y串但只需要O(n)
然后离线处理一下就好了
1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 using namespace std; 8 const int N=1e5+5; 9 char s[N]; 10 struct edge{ int next,to; edge(int next=0,int to=0) : next(next),to(to){}; }e[N]; 11 struct trie{ int th; trie *next[26],*fail,*fa; }t[N],*NEW=t,*root=t,*q[N],*now=t,*sth[N]; 12 struct Query{int x,y,id;}Q[N]; 13 int ade,l=1,r=1,df,n,c2; 14 int first[N],st[N],ed[N],BIT[N*2],ans[N]; 15 #define pn p->next[i] 16 #define pnf p->next[i]->fail 17 #define lowbit(x) (x&-x) 18 19 void modify(int x,int m){ 20 for (;x<=N;x+=lowbit(x)) BIT[x]+=m; 21 } 22 23 int query(int l,int r){ 24 int a1=0,a2=0; 25 for (;r;r-=lowbit(r)) a1+=BIT[r]; 26 for (l--;l;l-=lowbit(l)) a2+=BIT[l]; 27 return a1-a2; 28 } 29 30 void addedge(int x,int y){ 31 e[++ade]=edge(first[x],y),first[x]=ade; 32 } 33 34 trie *new1(trie *p){ NEW++; NEW->fa=p; return NEW; } 35 36 trie *insert(trie *p,int i,int x){ 37 if (!pn) pn=new1(p); 38 if (x!=0) modify(st[pn->th],1); 39 return pn; 40 } 41 42 trie *remove(trie *p,int x){ 43 if (x!=0) modify(st[p->th],-1); 44 return p->fa; 45 } 46 47 void build_fail(){ 48 trie *p=q[1]=root; 49 root->th=1; 50 for (int i=0;i<26;i++) if (pn) q[++r]=pn,pnf=root,pn->th=r,addedge(1,pn->th); 51 while (l<r){ 52 p=q[++l]; 53 for (int i=0;i<26;i++){ 54 if (pn){ 55 q[++r]=pn,pn->th=r; 56 for (pnf=p->fail ; pnf!=root && !pnf->next[i] ; pnf=pnf->fail); 57 if (pnf->next[i]) pnf=pnf->next[i]; 58 addedge(pnf->th,pn->th); 59 } 60 } 61 } 62 } 63 64 void dfs(int p){ 65 st[p]=++df; 66 for (int x=first[p];x;x=e[x].next){ 67 if (e[x].to) dfs(e[x].to); 68 } 69 ed[p]=df; 70 } 71 72 bool oper(Query a, Query b){return a.y<b.y;} 73 74 int main(){ 75 scanf("%s",s); 76 scanf("%d",&n); 77 for (int i=1;i<=n;i++) { 78 scanf("%d%d",&Q[i].x,&Q[i].y); 79 Q[i].id=i; 80 } 81 sort(Q+1,Q+1+n,oper); 82 for (int l=strlen(s),i=0;i<l;i++){ 83 if (s[i]>='a' && s[i]<='z') now=insert(now,s[i]-'a',0); 84 if (s[i]=='B') now=remove(now,0); 85 if (s[i]=='P') sth[++c2]=now; 86 } 87 build_fail(); 88 dfs(1); 89 now=root; 90 for (int i=1,j=0;i<=n;i++){ 91 while (sth[Q[i].y]!=now) { 92 if (s[j]>='a' && s[j]<='z') now=insert(now,s[j]-'a',1); 93 if (s[j]=='B') now=remove(now,1); 94 j++; 95 } 96 ans[Q[i].id]=query(st[sth[Q[i].x]->th],ed[sth[Q[i].x]->th]); 97 } 98 for (int i=1;i<=n;i++) printf("%d\n",ans[i]); 99 return 0; 100 }
竟然过了样例一次就A了。。