1. 程式人生 > >洛谷P3796 【模板】AC自動機(加強版)

洛谷P3796 【模板】AC自動機(加強版)

tor lse -h pty 自動機 IT printf sample 輸入格式

題目描述

NN 個由小寫字母組成的模式串以及一個文本串 TT 。每個模式串可能會在文本串中出現多次。你需要找出哪些模式串在文本串 TT 中出現的次數最多。

輸入輸出格式

輸入格式:

輸入含多組數據。

每組數據的第一行為一個正整數 NN ,表示共有 NN 個模式串, 1 \leq N \leq 1501N150 。

接下去 NN 行,每行一個長度小於等於 7070 的模式串。下一行是一個長度小於等於 10^6106 的文本串 TT 。

輸入結束標誌為 N=0N=0 。

輸出格式:

對於每組數據,第一行輸出模式串最多出現的次數,接下去若幹行每行輸出一個出現次數最多的模式串,按輸入順序排列。

輸入輸出樣例

輸入樣例#1: 復制
2
aba
bab
ababababac
6
beta
alpha
haha
delta
dede
tata
dedeltalphahahahototatalpha
0
輸出樣例#1: 復制
4
aba
2
alpha
haha

這題真是迷啊,開1e6的內存A了,開1e5的內存MLE

我們統計出每個節點的出現信息,然後暴力沿著$fail$樹跑就行了

// luogu-judger-enable-o2
// luogu-judger-enable-o2
// luogu-judger-enable-o2
// luogu-judger-enable-o2 #include<cstdio> #include<cstring> #include<queue> #include<vector> using namespace std; const int MAXN = 1e6 + 10, B = 26; int T; char s[201][75], a[MAXN]; int N; int fail[MAXN], ch[MAXN][27], val[MAXN], root = 0, tot = 0, sum[MAXN]; void insert(char
*s, int I) { int N = strlen(s + 1); int now = root; for(int i = 1; i <= N; i++) { int x = s[i] - a; if(!ch[now][x]) ch[now][x] = ++tot; now = ch[now][x]; } val[now] = I; } void GetFail() { queue<int> q; for(int i = 0; i < B; i++) if(ch[root][i]) q.push(ch[root][i]); while(!q.empty()) { int p = q.front(); q.pop(); for(int i = 0; i < B; i++) if(ch[p][i]) fail[ch[p][i]] = ch[fail[p]][i], q.push(ch[p][i]); else ch[p][i] = ch[fail[p]][i]; } } int main() { #ifdef WIN32 freopen("a.in", "r", stdin); #endif while(scanf("%d", &T) && T) { memset(fail, 0, sizeof(fail)); memset(ch, 0, sizeof(ch)); memset(val, 0, sizeof(val)); memset(fail, 0, sizeof(fail)); memset(sum, 0, sizeof(sum)); memset(s, 0, sizeof(s)); for(int i = 1; i <= T; i++) scanf("%s", s[i] + 1), insert(s[i], i); GetFail(); scanf("%s", a + 1); int N = strlen(a + 1), now = root; for(int i = 1; i <= N; i++) { now = ch[now][a[i] - a]; for(int t = now; t; t = fail[t]) if(val[t]) sum[val[t]]++; } int ans = 0; for(int i = 1; i <= T; i++) ans = max(ans, sum[i]); printf("%d\n", ans); for(int i = 1; i <= T; i++) if(sum[i] == ans) printf("%s\n", s[i] + 1); } return 0; }

洛谷P3796 【模板】AC自動機(加強版)