AC自动机

AC自动机是基于KMP思想和字典树的一种数据结构,是用来处理多模式匹配的。

至于详细的解释百度很多博客有。

我就记录一下模板

构造字典树

const int kind = 26;
struct node 
{
    node *fail;       //失败指针
    node *next[kind]; //Tire每个节点的个子节点(最多个字母)
    int count;        //是否为该单词的最后一个节点
    node()
    {           //构造函数初始化
        fail = NULL;
        count = 0;
        memset(next, NULL, sizeof(next));
    }
} *q[500001];          //队列,方便用于bfs构造失败指针
char keyword[51];     //输入的单词
char str[1000001];    //模式串
int head,tail;        //队列的头尾指针


插入数组

void insert(char *str) //建立Trie
{
    int temp, len;
    node *p = root;
    len = strlen(str);
    for(int i = 0; i < len; ++i)
    {
        temp = str[i] - 'a';
        if(p->next[temp] == NULL)
            p->next[temp] = new node();
        p = p->next[temp];
    }
    p->count++;
}




构造自动机

void build_ac_automation(node *root)
{
    head = tail = 0;//应该是这样吧
    int i;
    root->fail = NULL;
    q[head++] = root;
    while (head != tail)
    {
        node *temp = q[tail++];//当前指向的结点
        node *p = NULL;
        for (i = 0; i < 26; i++)
        {
            if (temp->next[i] != NULL)
            {
                if (temp == root) temp->next[i]->fail = root;//表示直接与root相连的结点
                else
                {
                    p = temp->fail;
                    while (p != NULL)//不断通过fali指针往上找
                    {
                        if (p->next[i] != NULL) //表示该节点存在一个与当前字母相同的儿子
                        {
                            temp->next[i]->fail = p->next[i];
                            break;
                        }
                        p = p->fail;
                    }
                    if (p == NULL) temp->next[i]->fail = root;//如果找到根节点了就指向根节点
                }
                q[head++] = temp->next[i];
            }
        }
    }
}

查询

int query(node *root)
    {
        int i = 0, cnt = 0, index, len = strlen(str);
        node *p = root;
        while (str[i]) 
        {
            index = str[i] - 'a';
            while (p->next[index] == NULL && p != root) p = p->fail;
            p = p->next[index];
            p = (p == NULL) ? root : p;
            node *temp = p;
            while (temp != root && temp->count != -1) 
            {
                cnt += temp->count;
                temp->count = -1;
                temp = temp->fail;
            }
            i++;
        }
        return cnt;
    }


(1)当前字符匹配,表示从当前节点沿着树边有一条路径可以到达目标字符,此时只需沿该路径走向下一个节点继续匹配即可,目标字符串指针移向下个字符继续匹配;(2)当前字符不匹配,则去当前节点失败指针所指向的字符继续匹配,匹配过程随着指针指向root结束。重复这2个过程中的任意一个,直到模式串走到结尾为止。


代码等转载自http://www.cppblog.com/mythit/archive/2009/04/21/80633.html

关于字典树的模板我可能更喜欢用kuangbin的,下次再说吧


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值