标签:后缀 ons div const show pre ret 模板 clu
1、uva 1449/LA 4670 Dominating Patterns
题意:有n个模板串和一个文本串,找出哪些模板串在文本串中出现次数最多。
思路:AC自动机模板
1 #include<cstring> 2 #include<queue> 3 #include<cstdio> 4 #include<map> 5 #include<string> 6 using namespace std; 7 8 const int SIGMA_SIZE = 26; 9 const int MAXNODE = 11000; 10 const int MAXS = 150 + 10; 11 12 map<string, int> ms; 13 14 struct ACTree 15 { 16 int ch[MAXNODE][SIGMA_SIZE]; 17 int f[MAXNODE]; // fail函数 18 int val[MAXNODE]; // 每个字符串的结尾结点都有一个非0的val 19 int last[MAXNODE]; // last[j]表示结点j沿着失配指针往回走时,遇到的下一个单词结点编号(后缀链接) 20 int cnt[MAXS]; 21 int sz; 22 23 void init() 24 { 25 sz = 1; 26 memset(ch[0], 0, sizeof(ch[0])); 27 memset(cnt, 0, sizeof(cnt)); 28 ms.clear(); 29 } 30 31 // 字符c的编号 32 int idx(char c) 33 { 34 return c - ‘a‘; 35 } 36 37 // 插入字符串。v必须非0 38 void insert(char *s, int v) 39 { 40 int u = 0, n = strlen(s); 41 for (int i = 0; i < n; i++) 42 { 43 int c = idx(s[i]); 44 if (!ch[u][c]) 45 { 46 memset(ch[sz], 0, sizeof(ch[sz])); 47 val[sz] = 0; 48 ch[u][c] = sz++; 49 } 50 u = ch[u][c]; 51 } 52 val[u] = v; 53 ms[string(s)] = v; 54 } 55 56 // 递归打印以结点j结尾的所有字符串 57 void Cnt(int j) 58 { 59 if (j) 60 { 61 cnt[val[j]]++; 62 Cnt(last[j]); 63 } 64 } 65 66 // 在T中找模板 67 int find(char* T) 68 { 69 int n = strlen(T); 70 int j = 0; // 当前结点编号,初始为根结点 71 for (int i = 0; i < n; i++) 72 { // 文本串当前指针 73 int c = idx(T[i]); 74 while (j && !ch[j][c]) j = f[j]; // 顺着失配边走,直到可以匹配 75 j = ch[j][c]; 76 if (val[j]) Cnt(j); 77 else if (last[j]) Cnt(last[j]); // 找到了 78 } 79 } 80 81 // 计算fail函数 82 void getFail() 83 { 84 queue<int> q; 85 f[0] = 0; 86 // 初始化队列 87 for (int c = 0; c < SIGMA_SIZE; c++) 88 { 89 int u = ch[0][c]; 90 if (u) 91 { 92 f[u] = 0; q.push(u); last[u] = 0; 93 } 94 } 95 // 按BFS顺序计算fail 96 while (!q.empty()) 97 { 98 int r = q.front(); q.pop(); 99 for (int c = 0; c < SIGMA_SIZE; c++) 100 { 101 int u = ch[r][c]; 102 if (!u) continue; 103 q.push(u); 104 int v = f[r]; 105 while (v && !ch[v][c]) v = f[v]; 106 f[u] = ch[v][c]; 107 last[u] = val[f[u]] ? f[u] : last[f[u]]; 108 } 109 } 110 } 111 112 }; 113 114 ACTree ac; 115 char text[1000001], P[151][80]; 116 int n, T; 117 118 int main() 119 { 120 while (scanf("%d", &n) == 1 && n) 121 { 122 ac.init(); 123 for (int i = 1; i <= n; i++) 124 { 125 scanf("%s", P[i]); 126 ac.insert(P[i], i); 127 } 128 ac.getFail(); 129 scanf("%s",text); 130 ac.find(text); 131 int best = -1; 132 for (int i = 1; i <= n; i++) 133 if (ac.cnt[i] > best) best = ac.cnt[i]; 134 printf("%d\n", best); 135 for (int i = 1; i <= n; i++) 136 if (ac.cnt[ms[string(P[i])]] == best) printf("%s\n", P[i]); 137 //不用ac.cnt[i]则是考虑模板串重复的情况,重复时后一个串会覆盖前一个串 138 } 139 return 0; 140 }
标签:后缀 ons div const show pre ret 模板 clu
原文地址:http://www.cnblogs.com/ivan-count/p/7498210.html