zoukankan      html  css  js  c++  java
  • HDU 2222 AC自动机 裸题

    题意:

    问母串中出现多少个模式串

    注意ac自动机的节点总数

    #include <stdio.h>
    #include <string.h>
    #include <queue>
    using namespace std;
    inline int Max(int a,int b){return a>b?a:b;}
    inline int Min(int a,int b){return a>b?b:a;}
    int ANS;
    
    
    #define N 1000010
    #define maxnode 250001
    #define sigma_size 26
    
    struct Trie{
    	int ch[maxnode][sigma_size];
    	int val[maxnode];
    	int last[maxnode];
    	int f[maxnode];
    	int sz;
    	void init(){
    		sz=1;
    		memset(ch,0,sizeof(ch));
    		memset(val, 0, sizeof(val));
    		memset(f,0,sizeof(f));
    		memset(last,0,sizeof(last));
    	}
    	int idx(char c){
    		return c-'a';
    	}
    	void print(int j){
    		if(j){
    			printf("%d: %d
    ", j, val[j]);
    			print(last[j]);
    		}
    	}
    	void Creat(char *s){
    		int u = 0, len = strlen(s);
    		for(int i = 0;i < len;i++){
    			int c = idx(s[i]);
    			if(!ch[u][c])
    				ch[u][c] = sz++;
    
    			u = ch[u][c];
    		}
    		val[u] ++;
    	}
    	void getFail(){
    		queue<int> q;
    		for(int i = 0; i<sigma_size; i++)
    			if(ch[0][i]) q.push(ch[0][i]);
    
    		while(!q.empty()){
    			int r = q.front(); q.pop();
    			for(int c = 0; c<sigma_size; c++){
    				int u = ch[r][c];
    				if(!u)continue;
    				q.push(u);
    				int v = f[r];
    				while(v && ch[v][c] == 0) v = f[v]; //沿失配边走上去 如果失配后有节点 且 其子节点c存在则结束循环
    				f[u] = ch[v][c];
    				last[u] = val[f[u]] ? f[u] : last[f[u]];
    			}
    		}
    	}
    	void find(char *T){
    		int len = strlen(T), j = 0;
    		for(int i = 0; i < len; i++){
    			int c = idx(T[i]);
    			while(j && ch[j][c]==0) j = f[j];
    			j = ch[j][c];
    
    			int temp = j;
    			while(temp && val[temp]){
    				ANS += val[temp];
    				val[temp] = 0;
    				temp = f[temp];
    			}
    		}
    	}
    };
    Trie ac;
    char S1[N];
    int Slen;
    
    void InputString(){
    	scanf("%s",S1);
    	Slen = strlen(S1);
    	S1[Slen]='';
    }
    int main(){
    
    	int T,i,j,n;scanf("%d",&T);
    
    	while(T--){
    		ac.init();
    		scanf("%d",&n);
    		while(n--){
    			scanf("%s",S1);
    			ac.Creat(S1);
    		}
    		ac.getFail();
    		InputString();
    		ANS = 0;
    		ac.find(S1);
    
    		printf("%d
    ",ANS);
    
    	}
    	return 0;
    }
    /*
    1
    5
    she
    he
    say
    shr
    her
    yasherhs
    
    ans:
    3
    
    
    
    */


  • 相关阅读:
    博客园开通新随笔
    遍历两个数组,并输出数组中的不同内容
    1021-二叉树复制和左右子树互换
    1020-层次遍历二叉树
    1019-计算二叉树的高度和结点数
    1018-深度遍历二叉树
    1017-乘积最大
    1016-求幂
    1015-最大公约数和最小公倍数
    1014-数据的插入与删除
  • 原文地址:https://www.cnblogs.com/riskyer/p/3356012.html
Copyright © 2011-2022 走看看