AC自动机 多字符串匹配 code

本文详细介绍了AC自动机的实现原理及其在多模式串匹配中的应用,包括构造、构建失败指针和匹配过程。通过实例演示了如何使用AC自动机进行高效匹配。

AC自动机 有多个匹配串适用



#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <queue> 
using namespace std; 
  
#define NUM (26) 
struct trienode {  
    trienode *fail;       // 失败指针
    trienode *next[NUM];  // Trie每个节点含26个孩子
    int count;            // 以该节点作为结尾的单词数量
    trienode() {          // 构造函数
        fail=NULL; 
        count=0; 
        memset(next, 0, sizeof(next)); 
    } 
};
 

 
void TrieInsert(trienode *root , const char *str)
{
	char ch;
    trienode *p = root; 
  
    while((ch = *str++)){ 
        int index = ch - 'a'; 
        if(p->next[index] == NULL) 
			p->next[index]= new trienode();  
        p = p->next[index];
    } 
	
    p->count++; 
	return;
}

void TrieCreate(trienode **root)
{
	*root = new trienode();
	
	return;
}

void TrieDestroy(trienode *root)
{
	trienode *p = root;
	
	if (!p)
		return;

	for (int i = 0; i < NUM; i++) {
		if (p->next[i])
			TrieDestroy(p->next[i]); 
	}
	
	delete p;
	
	return;
}


void BuildAc(trienode *root){
	queue<trienode *> qu;
	
    root->fail=NULL; 
    qu.push(root);
	
    while(!qu.empty()) {
		trienode *p=NULL; 
        trienode *temp = qu.front();
		qu.pop();
        
        for(int i = 0; i < NUM; i++) { 
            if(temp->next[i] != NULL) { 
                if(temp == root) 
					temp->next[i]->fail = root;                 
                else { 
                    p = temp->fail;
					while(p && p->next[i] == NULL)
						p = p->fail;
					temp->next[i]->fail = p ? p->next[i] : root; 
                } 
                qu.push(temp->next[i]);  
            } 
        }   
    }
	return;
} 

// Ac自动机多模式串匹配, 返回匹配的个数
int AcStrSearch(const char *str, trienode *root)
{
	char ch;
	int cnt = 0; 
    trienode *p = root;
	
	if (!str)
		return -1;
	
    while ((ch = *str++)) {  
        int index = ch - 'a';
		trienode *temp;
		
        while (p->next[index] == NULL && p != root)
			p = p->fail; 
        p = p->next[index]; 
        p = p ? p : root;
		
        temp = p;
        while(temp != root && temp->count != -1) { 
            cnt += temp->count; 
            temp->count = -1; 
            temp = temp->fail; 
        }                  
    }
    
    return cnt; 
} 


char pat[256];     // 输入的匹配串
char txt[100000];  // 输入的正文主串

int main(){ 
    int n1, n2;

	
    scanf("%d",&n1); 
    while(n1--){
		char *str;
		trienode *root;
		
		TrieCreate(&root);
         
        scanf("%d",&n2); 
        while(n2--){ 
            scanf("%s", pat); 
            TrieInsert(root, pat); 
        } 
        BuildAc(root);
		
        scanf("%s", txt);
		str = txt;		
        printf("%d\n", AcStrSearch(str, root));
		
		TrieDestroy(root);
    } 
	
    return 0; 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值