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 }

posted on 2012-06-16 19:15  myoi  阅读(410)  评论(0编辑  收藏  举报

导航