传送门
题意: 给你n个模式串, 再给你一个 文本串,问模式串在文本串中出现次数最多是多少。
出现次数最多的模式串有哪些。
解: 模版题。
#include#define LL long long #define rep(i, j, k) for(int i = j; i <= k; i++) #define dep(i, j, k) for(int i = k; i >= j; i--) #define mem(i, j) memset(i, j, sizeof(i)) using namespace std; const int N = 150 * 70 + 5, M = 26; map<string, int> vis; char s[1000005], b[155][100]; struct Trie { int a[N][M], tot, val[N], Fail[N], last[N]; ///last[j]:节点j沿着失配指针往回走时,遇到的下一个单词节点的编号 void init() { mem(a[0], -1); tot = 1; val[0] = -1; last[0] = 0; } int get(char Q) { return Q - 'a'; } void join(char s[], int v) { int len = strlen(s); int now = 0; rep(i, 0, len - 1) { int id = get(s[i]); if(a[now][id] == -1) { mem(a[tot], -1); val[tot] = -1; a[now][id] = tot++; } now = a[now][id]; } val[now] = v; } void getFail() { queue<int>Q; while(!Q.empty()) Q.pop(); Fail[0] = 0; rep(i, 0, M - 1) { if(a[0][i] == -1) a[0][i] = 0; else { Fail[a[0][i]] = 0; Q.push(a[0][i]); last[a[0][i]] = 0; } } while(!Q.empty()) { int now = Q.front(); Q.pop(); rep(i, 0, M - 1) { int u = a[now][i]; if(a[now][i] == -1) a[now][i] = a[Fail[now]][i]; else { Fail[u] = a[Fail[now]][i]; Q.push(u); last[u] = val[Fail[u]] == -1 ? last[Fail[u]] : Fail[u]; } } } } int num[155]; void print(int x) { if(x) { num[val[x]]++; print(last[x]); } } void query(char s[], int n) { mem(num, 0); int len = strlen(s); int now = 0; rep(i, 0, len - 1) { now = a[now][get(s[i])]; if(val[now] != -1) print(now); else if(last[now] != -1) print(last[now]); } int ma = 0; rep(i, 1, n) { ma = max(ma, num[i]); } printf("%d\n", ma); rep(i, 1, n) { if(num[vis[b[i]]] == ma) { printf("%s\n", b[i]); } } } }; Trie AC; int main() { int n; while(scanf("%d", &n) && n) { AC.init(); vis.clear(); rep(i, 1, n) { scanf("%s", b[i]); AC.join(b[i], i); vis[b[i]] = i; } AC.getFail(); scanf("%s", s); AC.query(s, n); } return 0; }