标签:
给定文本串$S$和若干模式串$\{T\}$, 对每个模式串$T$, 询问$T$是否为$S$的字串.
裸的AC自动机, 也可以用后缀数组做.
P.S. 这题数据很弱, 朴素的字符串匹配也能过.
模式串有重复的. 这样, 在建TRIE时就不能直接对每个模式串对应的节点 (尾节点) 标记上模式串的序号, 否则对于重复出现的模式串, 最后一次出现的那个会把在它之前的那些覆盖掉.
正确的做法是, 对于每个尾节点作唯一标号. 另外维护一个表$idx[]$, $idx[i]$表示第$i$个模式串的尾节点的标号.
另外要注意AC自动机的某些易错的实现细节, 代码注释有提及.
注释比较详细, 可作为模板.
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N{1<<20}, M{1<<10}; 5 6 bool res[M]; 7 int idx[M]; 8 char s[N], t[M]; 9 int ch[N][52], id[N], fail[N], last[N]; 10 11 12 int get_id(char ch){ 13 return islower(ch)?ch-‘a‘:ch-‘A‘+26; 14 } 15 16 queue<int> que; 17 18 int main(){ 19 // cout<<int(‘a‘)<<‘ ‘<<int(‘z‘)<<‘ ‘<<int(‘A‘)<<‘ ‘<<int(‘Z‘)<<endl; 20 int T; 21 for(cin>>T; T--; ){ 22 int q; 23 scanf("%s%d", s, &q); 24 int tail=0; 25 26 memset(res, false, sizeof(res)); //error-prone 27 28 memset(ch[tail], 0, sizeof(ch[tail])); 29 tail++; 30 31 for(int i=1; i<=q; i++){ 32 scanf("%s", t); 33 int u=0; 34 for(int j=0; t[j]; j++){ 35 int &v=ch[u][get_id(t[j])]; 36 if(!v){ 37 v=tail++; 38 memset(ch[v], 0, sizeof(ch[v])); 39 id[v]=0; 40 } 41 u=v; 42 } 43 if(!id[u]) id[u]=i; //error-prone: possibly duplicate patterns 44 idx[i]=id[u]; 45 } 46 47 for(int i=0; i<52; i++){ 48 int u=ch[0][i]; 49 if(u){ 50 que.push(u); 51 fail[u]=last[u]=0; //error-prone, must be initialized!! 52 } 53 } 54 55 for(; que.size(); ){ 56 int u=que.front(); 57 que.pop(); 58 for(int i=0; i<52; i++){ 59 //!view a variable (object) as an entity 60 int &v=ch[u][i]; 61 if(v){ //v is a new node, construct a new node of AC automata 62 que.push(v); 63 //no need to init. last[] and fail[], as they are is induced. 64 fail[v]=ch[fail[u]][i]; 65 last[v]=id[fail[v]]?fail[v]:last[fail[v]]; 66 } 67 else{ //the expected node v does not exist 68 v=ch[fail[u]][i]; 69 } 70 } 71 } 72 73 for(int i=0, u=0; s[i]; i++){ 74 u=ch[u][get_id(s[i])]; 75 res[id[u]]=true; 76 for(int v=last[u]; v; res[id[v]]=true, v=last[v]); //error-prone 77 } 78 79 for(int i=1; i<=q; i++) 80 puts(res[idx[i]]?"y":"n"); 81 82 } 83 }
上穷碧落下黄泉.
标签:
原文地址:http://www.cnblogs.com/Patt/p/5816531.html