AC自动机练习

AC自动机板子如下, 以求匹配次数最多的串为例.

const int N = 1e6+10;
int n, tot, ans;
char text[N], p[155][100];
int last[N], val[N];
int ch[N][26], f[N], cnt[155], fa[155];
queue<int> q;

void build() {
	f[0] = 0;
	REP(i,0,25) { 
		int u = ch[0][i];
		if (!u) continue;
		f[u] = 0, q.push(u), last[u] = 0;
	}
	while (q.size()) {
		int r = q.front(); q.pop();
		REP(i,0,25) { 
			int &u = ch[r][i], v=f[r];
			if (u) q.push(u),f[u]=ch[v][i],last[u]=val[f[u]]?f[u]:last[f[u]];
			else u=ch[v][i];
		}
	}
}
void query(char *s) {
	int n = strlen(s), j = 0;
	REP(i,0,n-1) {
		j = ch[j][s[i]-'a'];
		int t = val[j]?j:last[j];
		for (; t; t=last[t]) ++cnt[val[t]];
	}
}
void ins(char *s, int id) {
	int u = 0, n = strlen(s);
	REP(i,0,n-1) {
		int c = s[i]-'a';
		if (!ch[u][c]) { 
			ch[u][c] = ++tot;
			val[tot] = 0;
			memset(ch[tot],0,sizeof ch[tot]);
		}
		u = ch[u][c];
	}
	if (val[u]) fa[id] = u;
	else val[u] = id;
}

void init() {
	tot = 0;
	memset(cnt,0,sizeof cnt);
	memset(ch[0],0,sizeof ch[0]);
	REP(i,1,n) fa[i]=i;
}

void work() {
	init();
	REP(i,1,n) scanf("%s", p[i]), ins(p[i], i);
	build();
	scanf("%s", text);
	query(text);
	int ans = *max_element(cnt+1,cnt+1+n);
	printf("%d\n", ans);
	REP(i,1,n) if (cnt[fa[i]]==ans) puts(p[i]);
}

int main() {
	for (; scanf("%d", &n), n; ) work();
}

猜你喜欢

转载自www.cnblogs.com/uid001/p/10584412.html