zoukankan      html  css  js  c++  java
  • 【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
    ",ans[i]); 
     99     return 0;
    100 }
    View Code

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

  • 相关阅读:
    Linux基础命令---arch
    JSON漫谈
    django中外键关联表的查询随笔
    <django中render_to_response的可选参数和使用方法>
    有趣的Redis:缓存被我写满了,该怎么办?
    2020全球C++及系统软件技术大会成功落下帷幕
    AWS 宣布创建 Elasticsearch 和 Kibana 分支
    Flutter开发指南之理论篇:Dart语法05(单线程模型,事件循环模型,Isolate)
    自定义注解!绝对是程序员装逼的利器!!
    Java8 Stream
  • 原文地址:https://www.cnblogs.com/karl07/p/6657422.html
Copyright © 2011-2022 走看看