• noi 2011 阿狸的打字机 AC自动机


    题意: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有28个按键,分别印有26个小写英文字母和'B'、'P'两个字母。

    经阿狸研究发现,这个打字机是这样工作的:

    l 输入小写字母,打字机的一个凹槽中会加入这个字母(这个字母加在凹槽的最后)。

    l 按一下印有'B'的按键,打字机凹槽中最后一个字母会消失。

    l 按一下印有'P'的按键,打字机会在纸上打印出凹槽中现有的所有字母并换行,但凹槽中的字母不会消失。

    例如,阿狸输入aPaPBbP,纸上被打印的字符如下:

    a

    aa

    ab

    我们把纸上打印出来的字符串从1开始顺序编号,一直到n。打字机有一个非常有趣的功能,在打字机中暗藏一个带数字的小键盘,在小键盘上输入两个数(x,y)(其中1≤x,y≤n),打字机会显示第x个打印的字符串在第y个打印的字符串中出现了多少次。

    阿狸发现了这个功能以后很兴奋,他想写个程序完成同样的功能,你能帮助他么?

    思路:按题目所说的建字母树

    然后就出failink,失败指针

    然后 按failink建一棵树

    题目所求的(x,y) 就是在failink树中,以x为根的子树与字母树从根节点到y的两个集合的交集

    在failink树上求一下dfs序

    然后离线做字母树

    时间复杂度nlogn(n是文本总长度)

    P.S. 第一次用vim写的题

      1 #include<iostream>
      2 #include<cmath>
      3 #include<cstdio>
      4 #include<cstring>
      5 #include<vector>
      6 using namespace std;
      7 #define MAXN 110000
      8 struct node
      9 {
     10     int name,num;
     11     vector<int> id;
     12     node *next[27],*failink,*father;
     13     node()
     14     {
     15         memset(next,0,sizeof(next));
     16     }
     17 };
     18 struct tree_node
     19 {
     20     int num;
     21     tree_node *next;
     22 };
     23 node *Q[MAXN], *head,memo[MAXN];
     24 int high[MAXN],low[MAXN];
     25 int father[MAXN];
     26 tree_node *graph[MAXN],tree_memo[MAXN];
     27 int n,m,top=0,node_num=0,label=0;
     28 int tree[MAXN];
     29 int map[MAXN];
     30 int ans[MAXN];
     31 vector <pair<int,int> > ask[MAXN];
     32 char c[MAXN];
     33 int lowbit(int x)
     34 {
     35     return x&(x^(x-1));
     36 }
     37 void change(int pos,int x)
     38 {
     39     for(pos;pos<=label;pos+=lowbit(pos))
     40         tree[pos]+=x;
     41 }
     42 int sum(int x)
     43 {
     44     int ans=0;
     45     for(x;x>0;x-=lowbit(x))
     46         ans+=tree[x];
     47     return ans;
     48 }
     49 void insert()
     50 {
     51     n=strlen(c);
     52     head=&memo[top++]; head->num=0; head->failink=head; head->id.push_back(0);
     53     int i,x;
     54     node *t=head,*p;
     55     for(i=0;i<n;i++)
     56     {
     57         if(c[i]!='B'&&c[i]!='P')
     58         {
     59             x=c[i]-'a';
     60             if(t->next[x]==NULL)
     61             {
     62                 p=&memo[top++];
     63                 p->father=t; t->next[x]=p;p->num=top-1; p->name=x;
     64             }
     65             t=t->next[x];
     66         }
     67         else if(c[i]=='P')
     68         {
     69             t->id.push_back(++node_num);
     70             map[node_num]=t->num;
     71         }
     72         else
     73             t=t->father;
     74     }
     75 }
     76 void add(int x,int y)
     77 {
     78     tree_node *p=&tree_memo[top++];
     79     p->num=y; p->next=graph[x]; graph[x]=p;
     80 }
     81 void set_failink()
     82 {
     83     top=0;
     84     int left,right=0;
     85     Q[left=right=1]=head;
     86     node *p,*t;
     87     int x;
     88     while(left<=right)
     89     {
     90         p=Q[left++];
     91         if(p->father==head)
     92         {
     93             p->failink=head;
     94         }
     95         else if(p!=head)
     96         {
     97             t=p->father->failink;
     98             x=p->name;
     99             while(1)
    100             {
    101                 if(t->next[x]!=NULL)
    102                 {
    103                     p->failink=t->next[x];
    104                     break;
    105                 }
    106                 if(t==head)
    107                 {
    108                     p->failink=head;
    109                     break;
    110                 }
    111                 t=t->failink;
    112             }
    113         }
    114         if(p!=head)
    115             add(p->failink->num,p->num);
    116         for(int i=0;i<26;i++)
    117         {
    118             if(p->next[i]!=NULL)
    119                 Q[++right]=p->next[i];
    120         }
    121     }
    122     ///out<<left<<" "<<right<<endl;
    123 }
    124 void dfs(int x)
    125 {
    126     //cout<<x<<" "<<label<<endl;
    127     low[x]=++label;
    128     tree_node *p;
    129     for(p=graph[x];p;p=p->next)
    130         dfs(p->num);
    131     high[x]=label;
    132 }
    133 
    134 void dfs2(node *t)
    135 {
    136     int i;
    137     vector <pair<int,int> >:: iterator j;
    138     if(t==head)
    139     {
    140         for(i=0;i<26;i++)
    141             if(t->next[i]!=NULL)
    142                 dfs2(t->next[i]);
    143         return ;
    144     }
    145     change(low[t->num],1);
    146     for(i=0;i<t->id.size();i++)
    147     {
    148         for(j=ask[t->id[i]].begin();j!=ask[t->id[i]].end();j++)
    149         {
    150             ans[j->second]=sum(high[map[j->first]])-sum(low[map[j->first]]-1);
    151         }
    152     }
    153     for(i=0;i<26;i++)
    154         if(t->next[i]!=NULL)
    155             dfs2(t->next[i]);
    156     change(low[t->num],-1);
    157     return ;
    158 }
    159 int main()
    160 {
    161     int i;
    162     memset(tree,0,sizeof(tree));
    163     memset(graph,0,sizeof(graph));
    164     scanf("%s",c);
    165     insert();
    166     set_failink();
    167     //cout<<head->next[0]->id[0]<<" "<<head->next[0]->next[0]->failink->id[0]<<" "<<head->next[0]->next[1]->failink->id[0]<<endl;
    168     //cout<<head->next[0]->name<<endl;
    169     dfs(0);
    170     //for(i=0;i<4;i++)
    171     //<F5>    cout<<high[i]<<" "<<low[i]<<endl;
    172     scanf("%d",&m);
    173     int x,y;
    174     for(i=1;i<=m;i++)
    175     {
    176         scanf("%d%d",&x,&y);
    177         ask[y].push_back(make_pair(x,i));
    178     }
    179     dfs2(head);
    180     for(i=1;i<=m;i++)
    181         printf("%d\n",ans[i]);
    182     return 0;
    183 }
  • 相关阅读:
    剑指offer4:重建二叉树(后序遍历)
    剑指offer3:从尾到头打印链表每个节点的值
    剑指offer2:C++实现的替换空格(字符中的空格替换为“%20”)
    tp5系统变量输出(可以用来传递搜索的参数)
    Ajax实现文件上传的临时垃圾文件回收策略
    php获取当天的开始时间和结束时间
    Think PHP递归获取所有的子分类的ID (删除当前及子分类)
    tp查找某字段,排除某字段,不用一次写那么多
    git-查看历史版本及回滚版本
    dedecms目录结构,非常全
  • 原文地址:https://www.cnblogs.com/myoi/p/2552038.html
Copyright © 2020-2023  润新知