题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2896
题意: 中文题诶~
思路: ac自动机
这里要求记录匹配的模式串的编号, 不过题目中说明了不同模式串对应的编号是不同的, 所以可以直接用 end 数组记录编号即可, 然后与主串匹配成功的标记一下即可.
代码:
1 #include <iostream> 2 #include <stdio.h> 3 #include <string.h> 4 #include <queue> 5 using namespace std; 6 7 const int MAXN = 500 * 200 + 10; 8 int sol[510]; 9 10 struct Trie{ 11 int next[MAXN][128], fail[MAXN], end[MAXN]; 12 int root, L; 13 int newnode(){//初始化字典树节点 14 for(int i = 0; i < 128; i++){ 15 next[L][i] = -1; 16 } 17 end[L++] = 0; 18 return L - 1; 19 } 20 void init(){//初始化字典树根节点 21 L = 0; 22 root = newnode(); 23 } 24 void insert(char buf[], int id){//往字典树中插入一个单词 25 int len = strlen(buf); 26 int now = root; 27 for(int i = 0; i < len; i++){ 28 if(next[now][buf[i]] == -1) next[now][buf[i]] = newnode(); 29 now = next[now][buf[i]]; 30 } 31 end[now] = id;//记录编号 32 } 33 void build(){ //构造fail数组 34 queue<int> Q; 35 fail[root] = root; 36 for(int i = 0; i < 128; i++){ 37 if(next[root][i] == -1) next[root][i] = root; 38 else{ 39 fail[next[root][i]] = root; 40 Q.push(next[root][i]); 41 } 42 } 43 while(!Q.empty()){ 44 int now = Q.front(); 45 Q.pop(); 46 for(int i = 0; i < 128; i++) 47 if(next[now][i] == -1) next[now][i] = next[fail[now]][i]; 48 else{ 49 fail[next[now][i]] = next[fail[now]][i]; 50 Q.push(next[now][i]); 51 } 52 } 53 } 54 bool query(char buf[]){ 55 int len = strlen(buf); 56 int now = root; 57 bool flag = false; 58 for(int i = 0; i < len; i++){ 59 now = next[now][buf[i]]; 60 int temp = now; 61 while(temp != root){ 62 if(end[temp]){ 63 sol[end[temp]] = 1; 64 flag = true; 65 } 66 temp = fail[temp]; 67 } 68 } 69 return flag; 70 } 71 void debug(){ 72 for(int i = 0; i < L; i++){ 73 printf("id = %3d,fail = %3d,end = %3d,chi = [",i,fail[i],end[i]); 74 for(int j = 0; j < 26; j++){ 75 printf("%2d",next[i][j]); 76 } 77 printf("] "); 78 } 79 } 80 }; 81 82 Trie ac; 83 char buf[MAXN]; 84 85 int main(void){ 86 int n, m; 87 while(~scanf("%d", &n)){ 88 ac.init(); 89 int tot = 0; 90 for(int i = 1; i <= n; i++){ 91 scanf("%s", buf); 92 ac.insert(buf, i); 93 } 94 ac.build(); 95 scanf("%d", &m); 96 for(int i = 1; i <= m; i++){ 97 scanf("%s", buf); 98 bool flag = ac.query(buf); 99 if(flag){ 100 tot += 1; 101 printf("web %d:", i); 102 for(int j = 1; j <= n; j++){ 103 if(sol[j]){ 104 sol[j] = 0; 105 printf(" %d", j); 106 } 107 } 108 puts(""); 109 } 110 } 111 printf("total: %d ", tot); 112 } 113 return 0; 114 }