题意: 阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机。打字机上只有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 }