歌名 - 歌手
0:00

    AC自动机

    前言

    其实AC自动机就是多模式匹配,运用trie和kmp把时间复杂度优化到线性的O(N)。

    一、建trie

    trie就不多说了,相信大家都会

    void put()
    {
        int now=1,len=strlen(s1+1);
        for(int i=1;i<=len;i++)
        {
            if(!trie[now].c[s1[i]-'a']) trie[now].c[s1[i]-'a']=++tot;
            trie[trie[now].c[s1[i]-'a']].deep=trie[now].deep+1;
            now=trie[now].c[s1[i]-'a'];
        }
        trie[now].w=1;
    }
    

    二、构建fail(失败指针)

    fail(失败指针)其实就是类似于kmp的next数组,是AC自动机的核心。
    如果会kmp的话,应该也不能难解。
    可以通过一幅图来理解一下
    这里写图片描述

    void makefail()
    {
        int head=0,tail=1,now=1;
        d[1]=1;
        trie[1].fail=0;
        while(head<tail)
        {
            int k=d[++head],p=0;
            for(int i=0;i<26;i++)
            {
                if(!trie[k].c[i]) continue;
                p=trie[k].c[i];
                int z=trie[k].fail;
                while(z && !trie[z].c[i]) z=trie[z].fail;
                trie[p].fail=trie[z].c[i];
                trie[p].fail=trie[p].fail?trie[p].fail:1;
                d[++tail]=p;
            }
        }
    }
    

    三、查询

    当每次确定了一个节点后顺着fail构成了链向上走,避免漏算以现在搜到的状态为后缀的字符串。

    int find()
    {
    	int j=1;
    	for(int i=1;i<=n;i++)
    	{
    		int index=s[i]-'a';
    		while(j!=1 && !trie[j].c[index]) j=trie[j].fail;
    		j=trie[j].c[index];
    		j=j?j:1;
    		int p=j;
    		while(p!=1)
    		{
    			if(trie[p].w) ans++;
    			p=trie[p].fail;
    			trie[p].w--;
    		}
    	}
    }
    

    当然,不能直接打模板,根据每到题目的不同来分析运用,有时要加点优化。


    模板题【GDOI2013模拟4】贴瓷砖

    posted @ 2018-05-16 20:58  无尽的蓝黄  阅读(131)  评论(0编辑  收藏  举报