您的位置:首页 > 其它

AC自动机模板

2017-06-24 18:27 344 查看
大意:

给你一些模板串, 然后给你一些文本串, 对于每个文本串, 输出它中间出现次数最多的模板串和次数(可能有多个);

这当然是模板。。。。。。。。。。。。。。。。。。

代码:

#include<queue>
#include<cstdio>
#include<cstring>

#define maxn 15000
#define maxc 1000005
#define For(a, b, c) for(a = b; a <= (int)(c); ++a)
using namespace std;
int n;
char T[maxc], P[151][71];
inline int idx(char c){ return c - 'a'; }

struct Trie{
int sz, ch[maxn][26], val[maxn];
inline void init(){
sz = 0;
memset(ch, 0, sizeof(ch));
memset(val, 0, sizeof(val));
}
inline void insert(char *s, int v){
int i, u = 0, l = strlen(s);
For(i, 0, l - 1){
int c = idx(s[i]);
if(!ch[u][c]) ch[u][c] = ++sz;
u = ch[u][c];
}
val[u] = v;
}
}tr;

struct AC_machine{
int fail[maxn], last[maxn], cnt[maxn];
inline void init(){
memset(fail, 0, sizeof(fail));
memset(last, 0, sizeof(last));
memset(cnt, 0, sizeof(cnt));
}
inline void getfail(){
int c, u, k, r;
queue<int> q;
fail[0] = 0;
For(c, 0, 25){
if(tr.ch[0][c]) q.push(tr.ch[0][c]);
}
while(!q.empty()){
r = q.front(), q.pop();
For(c, 0, 25){
u = tr.ch[r][c];
if(!u){ tr.ch[r][c] = tr.ch[fail[r]][c]; continue; }
q.push(u);
k = fail[r];
while(k && !tr.ch[k][c]) k = fail[k];
fail[u] = tr.ch[k][c];
last[u] = tr.val[fail[u]] ? fail[u] : last[fail[u]];
}
}
}
inline void calc(int x){
while(x){
++cnt[tr.val[x]];
x = last[x];
}
}
inline void find(char *s){
int i, j, l = strlen(s);
For(i, 0, l - 1){
j = tr.ch[j][idx(s[i])];
if(tr.val[j]) calc(j);
else if(last[j]) calc(last[j]);
}
}
}ac;

int main(){
int i;
while(scanf("%d", &n), n){
tr.init();
ac.init();
For(i, 1, n) scanf("%s", P[i]), tr.insert(P[i], i);
scanf("%s", T);
ac.getfail();
ac.find(T);
int best = -1;
For(i, 1, n) if(ac.cnt[i] > best) best = ac.cnt[i];
printf("%d\n", best);
For(i, 1, n) if(ac.cnt[i] == best){
printf("%s\n", P[i]);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  AC自动机