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

    题目链接:

    ac自动机的精华在于 (fail) 指针,
    为了避免暴力跳 (fail) 指针使得复杂度爆炸,建出 (fail) 图就好了

    P3808
    https://www.luogu.com.cn/problem/P3808

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 1000010; 
    
    int n, rt = 0, tot = 0; 
    ll ans = 0;
    struct Node{
    	int son[30], sz, fail;
    }t[maxn];
    
    char s[maxn];
    
    void insert(){
    	int p = rt;
    	int len = strlen(s);
    	for(int i = 0 ; i < len ; ++i){
    		if(!t[p].son[s[i] - 'a']){
    			t[p].son[s[i] - 'a'] = ++tot;
    		}
    		p = t[p].son[s[i] - 'a'];
    	} 
    	++t[p].sz;
    }
    
    queue<int> q; 
    void build(){
    	t[rt].fail = rt;
    	for(int i = 0 ; i <= 25 ; ++i){
    		if(t[rt].son[i]) q.push(t[rt].son[i]);
    	}
    	
    	while(!q.empty()){
    		int u = q.front(); q.pop();
    		for(int i = 0 ; i <= 25 ; ++i){
    			if(t[u].son[i]){
    				t[t[u].son[i]].fail = t[t[u].fail].son[i];
    				q.push(t[u].son[i]);
    			} else{
    				t[u].son[i] = t[t[u].fail].son[i];
    			}
    		}
    	}
    }
    
    void query(){
    	int p = rt;
    	int len = strlen(s);
    	for(int i = 0 ; i < len ; ++i){
    		p = t[p].son[s[i] - 'a'];
    		for(int j = p ; j && ~t[j].sz ; j = t[j].fail) ans += t[j].sz, t[j].sz = -1;
    	}
    }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	n = read();
    	for(int i = 1 ; i <= n ; ++i){
    		scanf("%s", s);
    		insert();
    	}
    	
    	build();
    	
    	scanf("%s", s);
    	query();
    	
    	printf("%lld
    ", ans);
    	
    	return 0;
    }
    

    P3796
    https://www.luogu.com.cn/problem/P3796

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 20010; 
    
    int n, rt = 0, tot = 0; 
    int ans[maxn], c[maxn], mx;
    
    struct Node{
    	int son[30], en, fail;
    }t[maxn];
    
    char s[200][100];
    char txt[1000010];
    
    void insert(int num){
    	int p = rt;
    	int len = strlen(s[num]);
    	for(int i = 0 ; i < len ; ++i){
    		if(!t[p].son[s[num][i] - 'a']){
    			t[p].son[s[num][i] - 'a'] = ++tot;
    		}
    		p = t[p].son[s[num][i] - 'a'];
    	} 
    	t[p].en = tot;
    	c[num] = tot;
    }
    
    void build(){
    	queue<int> q; 
    	t[rt].fail = rt;
    	for(int i = 0 ; i <= 25 ; ++i){
    		if(t[rt].son[i]) q.push(t[rt].son[i]);
    	}
    	
    	while(!q.empty()){
    		int u = q.front(); q.pop();
    		for(int i = 0 ; i <= 25 ; ++i){
    			if(t[u].son[i]){
    				t[t[u].son[i]].fail = t[t[u].fail].son[i];
    				q.push(t[u].son[i]);
    			} else{
    				t[u].son[i] = t[t[u].fail].son[i];
    			}
    		}
    	}
    }
    
    void query(){
    	int p = rt;
    	int len = strlen(txt);
    	for(int i = 0 ; i < len ; ++i){
    		p = t[p].son[txt[i] - 'a'];
    		for(int j = p ; j ; j = t[j].fail) {
    			++ans[t[j].en];
    			if(t[j].en) mx = max(mx, ans[t[j].en]);
    		}
    	}
    }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	while(1){
    		memset(t, 0, sizeof(t));
    		memset(ans, 0, sizeof(ans));
    		memset(c, 0, sizeof(c));
    		mx = 0; tot = 0;
    		n = read();
    		if(!n) break;
    		for(int i = 1 ; i <= n ; ++i){
    			scanf("%s", s[i]);
    			insert(i);
    		}
    		
    		build();
    		
    		scanf("%s", txt);
    		query();
    		
    		printf("%d
    ", mx);
    		for(int i = 1 ; i <= n ; ++i){
    			if(ans[c[i]] == mx) printf("%s
    ", s[i]);
    		}
    	}
    
    	return 0;
    }
    

    P5357 https://www.luogu.com.cn/problem/P5357
    (fail) 树上差分

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    using namespace std;
    typedef long long ll;
    
    const int maxn = 200010;
    
    int n, rt = 0, tot = 0; 
    int ans[maxn], c[maxn], mx;
    
    struct Node{
    	int son[30], en, fail;
    }t[maxn];
    
    int h[maxn], cnt = 0;
    
    struct E{
    	int to, next;
    }e[maxn << 1];
    
    void add(int u, int v){
    	e[++cnt].to = v;
    	e[cnt].next = h[u];
    	h[u] = cnt;
    }
    
    char s[2000010];
    char txt[2000010];
    
    void insert(int num){
    	int p = rt;
    	int len = strlen(s);
    	for(int i = 0 ; i < len ; ++i){
    		if(!t[p].son[s[i] - 'a']){
    			t[p].son[s[i] - 'a'] = ++tot;
    		}
    		p = t[p].son[s[i] - 'a'];
    	} 
    	t[p].en = p;
    	c[num] = p;
    }
    
    void build(){
    	queue<int> q; 
    	t[rt].fail = rt;
    	for(int i = 0 ; i <= 25 ; ++i){
    		if(t[rt].son[i]) {
    			add(rt, t[rt].son[i]);
    			q.push(t[rt].son[i]);
    		}
    	}
    	
    	while(!q.empty()){
    		int u = q.front(); q.pop();
    		for(int i = 0 ; i <= 25 ; ++i){
    			if(t[u].son[i]){
    				t[t[u].son[i]].fail = t[t[u].fail].son[i];
    				add(t[u].son[i], t[t[u].son[i]].fail);
    				add(t[t[u].son[i]].fail, t[u].son[i]);
    				q.push(t[u].son[i]);
    			} else{
    				t[u].son[i] = t[t[u].fail].son[i];
    			}
    		}
    	}
    }
    
    int d[maxn];
    
    void query(){
    	int p = rt;
    	int len = strlen(txt);
    	for(int i = 0 ; i < len ; ++i){
    		p = t[p].son[txt[i] - 'a'];
    		++d[p];
    //		printf("%d ", p);
    	}
    }
    
    void dfs(int u, int par){
    //	printf("%d ", u);
    	for(int i = h[u] ; i != -1 ; i = e[i].next){
    		int v = e[i].to;
    		if(v == par) continue; 
    		dfs(v, u);
    		d[u] += d[v];
    	}
    }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	while(scanf("%d", &n) != EOF){
    		memset(h, -1, sizeof(h));
    		memset(t, 0, sizeof(t));
    		memset(ans, 0, sizeof(ans));
    		memset(c, 0, sizeof(c));
    		mx = 0; tot = 0;
    		for(int i = 1 ; i <= n ; ++i){
    			scanf("%s", s);
    			insert(i);
    		}
    		
    		build();
    		
    		scanf("%s", txt);
    		query();
    //		printf("
    ");
    		
    		dfs(0, 0);
    //		printf("
    ");
    		
    		for(int i = 1 ; i <= n ; ++i){
    			printf("%d
    ", d[c[i]]);
    		}
    	}
    
    	return 0;
    }
    
  • 相关阅读:
    Linux重定向命令
    ls命令
    Linux常用命令_(进程管理)
    Linux常用命令_(文件操作)
    Linux常用命令_(文件查看)
    Linux常用命令_(文件搜索)
    Oracle表空间管理
    如何测试数据库表空间不足场景
    find命令
    各种比例尺标准分幅图经差、纬差表
  • 原文地址:https://www.cnblogs.com/tuchen/p/14189350.html
Copyright © 2011-2022 走看看