zoukankan      html  css  js  c++  java
  • AC自动机

    AC自动机

    ​ 给你\(n\)个模式串和1个文本串,问有多少个模式串在文本串里出现过。

    ​ 这就是AC自动机解决的问题,得用到Tire树和\(KMP\)的思想。

    ​ 如果我们枚举每一个模式串去和文本串匹配,那么复杂度是\(O(n^2)\)的。

    ​ 现在我们把每个模式串放到一颗Tire树上,根据\(KMP\)的思想搞一个\(fail\)数组,这个数组表示当前节点匹配不到了应该从哪里接着匹配,因为每次都从头开始匹配相当于还是\(n^2\)的。

    ​ 这个\(fail\)数组和\(KMP\)里的\(nxt\)数组都叫失配指针,可以看成是Tire树上一个字符连到另一个相同字符的东西。

    大佬的博客

    ​ 我们先建一颗Tire树:[\(she, shr, say, her\)]

    ​ 连完\(fail\)数组是这样的:

    ​ 我们可以\(bfs\)求出\(fail\)数组,根的每个子节点都指向根,其它节点指向它父亲的\(fail\)的相同的子节点,如果没有相同的,指向根(0)就好了。

    ​ 还有一个注意的地方,找完“she”里面的“e”后,会找到“her”里面的“r"。(对应bfs里面的那个else)

    #include <iostream>
    #include <cstdio>
    #include <queue>
    #include <cstring>
    
    using namespace std;
    
    const int N = 1e6;
    int n, cnt;
    int ch[N][26], fail[N], val[N];
    char a[N], b[N];
    
    struct AC {
    	void ins(char *a) {
    		int len = strlen(a), p = 0;
    		for(int i = 0;i < len; i++) {
    			int num = a[i] - 'a';
    			if(!ch[p][num]) ch[p][num] = ++cnt;
    			p = ch[p][num];
    		}
    		val[p]++;
    	}
    	
    	void make_fail() {
    		queue <int> q;
    		for(int i = 0;i < 26; i++) {
    			if(ch[0][i]) fail[ch[0][i]] = 0, q.push(ch[0][i]); 
    		}
    		while(q.size()) {
    			int x = q.front(); q.pop();
    			for(int i = 0;i < 26; i++) {
    				if(ch[x][i]) fail[ch[x][i]] = ch[fail[x]][i], q.push(ch[x][i]);
    				else ch[x][i] = ch[fail[x]][i];
    			}
    		}
    	}
    	
    	int match(char *b) {
    		int len = strlen(b), p = 0, ans = 0;
    		for(int i = 0;i < len; i++) {
    			int num = b[i] - 'a';
    			p = ch[p][num];
    			for(int t = p;t && ~val[t]; t = fail[t]) ans += val[t], val[t] = -1; //~(-1) =  0
    		}
    		return ans;
    	}
    } cj;
    
    int main() {
    
    	scanf("%d", &n);
    	for(int i = 1;i <= n; i++) { cin >> a; cj.ins(a); }
    	cj.make_fail();
    	cin >> b;
    	printf("%d", cj.match(b));
    	
    	return 0;
    }
    
  • 相关阅读:
    private SortedDictionary<string, object> Dic_values = new SortedDictionary<string, object>();
    [Luogu 2817]宋荣子的城堡
    [测试题]等效集合
    [SDOI 2009]HH去散步
    [HNOI 2013]比赛
    [SCOI 2016]背单词
    [测试题]圆圈
    [Luogu 3389]【模板】高斯消元法
    [Codeforces 505C]Mr. Kitayuta, the Treasure Hunter
    [Codeforces 448C]Painting Fence
  • 原文地址:https://www.cnblogs.com/czhui666/p/13383480.html
Copyright © 2011-2022 走看看