【bzoj2434】: [Noi2011]阿狸的打字机 字符串-AC自动机-BIT

【bzoj2434】: [Noi2011]阿狸的打字机

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 }
View Code

竟然过了样例一次就A了。。

posted @ 2017-04-01 20:25  karl07  阅读(187)  评论(0编辑  收藏  举报