Aho-Corasick automaton 模板

typedef struct Node* node;

const int MAXNs = ;//模式串最大長度 
const int MAXNS = ;//文章(待匹配串)最大長度 

struct Node{
    node next[26];
    node fail;//失配指针
    int sum;
    Node(){
    	sum = 0;
    	fail = NULL;
    	memset(next,NULL,sizeof next);
	}
};

char s[MAXNs];//模式串

void Insert(node root)//字典树的建立
{
    node p = root;
    int len = strlen(s);
    for(int i=0 ; i<len ; ++i)
    {
        int x = s[i] - 'a';
        if(p->next[x] == NULL)
        {
            node newnode = new Node();
            p->next[x] = newnode;
        }
        p = p->next[x];
    }
    p->sum++;
}

void build_fail_pointer(node root)//构造fail指针
{
    queue<node> Q;
    Q.push(root);
    node p,temp;
    while(!Q.empty())
    {
        temp = Q.front();
        Q.pop();
        for(int i=0 ; i<26 ; ++i)
        {
            if(temp->next[i])
            {
                if(temp == root)
                {
                    temp->next[i]->fail = root;
                }
                else
                {
                    p = temp->fail;
                    while(p)
                    {
                        if(p->next[i])
                        {
                            temp->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if(p == NULL) temp->next[i]->fail = root;
                }
                Q.push(temp->next[i]);
            }
        }
    }
}

char S[MAXNS];//文章(待匹配串)

int ac_automation(node root)//利用fail指针进行匹配。
{
    node p = root;
    int len = strlen(S);
    int ans = 0;
    for(int i=0 ; i<len ; ++i)
    {
        int x = S[i] - 'a';
        while(!p->next[x] && p != root) p = p->fail;
        p = p->next[x];
        if(!p) p = root;
        node temp = p;
        while(temp != root)
        {
           if(temp->sum >= 0)
           {
               ans += temp->sum;
               temp->sum = -1;
           }
           else break;
           temp = temp->fail;
        }
    }
    return ans;
}

void Del(node root){
	for(int i=0 ; i<26 ; ++i){
		if(root->next[i])Del(root->next[i]);
	}
	delete(root);
}
	
int main(){
	
	int T;// case數量 
	scanf("%d",&T);
	while(T--){
		int N;//模式串數量 
		node root = new Node();
		scanf("%d",&N);
		while(N--){
			scanf("%s",s);
			Insert(root);
		}
		scanf("%s",S);
		build_fail_pointer(root);//构造fail指针
		printf("%d\n",ac_automation(root));
		Del(root);
	}
	
	return 0;
}

 

posted @ 2018-08-06 11:01  Assassin_poi君  阅读(177)  评论(0编辑  收藏  举报