码迷,mamicode.com
首页 > 其他好文 > 详细

AC自动机

时间:2014-10-02 22:59:53      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:style   blog   http   color   os   使用   ar   for   sp   

假设手里有N个串,和原文进行匹配,如果跑KMP,得把原文跑N次,实在是太费时间了。AC自动机借助于Trie的压缩功能,将多个串压成一个“树”,用这个树进行KMP,这就是贝尔实验室发明的AC自动机。
AC自动机主要有三个操作;insert,getfail,print,find。
insert的操作和Trie一样。
bubuko.com,布布扣
void Insert(string str,int v)
{
    int u=0,c;
    for(int i=0;i<str.size();i++)
    {
        c=str[i]-a;
        if(!ch[u][c])
        {
            val[sz]=0;
            ch[u][c]=sz++;
        }
        u=ch[u][c];
    }
    val[u]=v;
}
insert的操作

getfail采用BFS,逐个检查,记录后缀链接last数组

bubuko.com,布布扣
void GetFail()
{
    queue<int> Q;
    f[0]=0;
    for(int c=0;c<26;c++)
    {
        int u=ch[0][c];
        if(u)
        {
            f[u]=last[u]=0;
            Q.push(u);
        }
    }
    while(!Q.empty())
    {
        int r=Q.front();Q.pop();
        for(int c=0;c<26;c++)
        {
            int u=ch[r][c];
            if(!u)
            {
                ch[r][c]=ch[f[r]][c];
                continue;
            }
            Q.push(u);
            int v=f[r];
            while(v&&!ch[v][c]) v=f[v];
            f[u]=ch[v][c];
            last[u]=val[f[u]]?f[u]:last[f[u]];
        }
    }
}
getfail的操作

find对应的是原文

bubuko.com,布布扣
void Find(string str)
{
    int j=0,c;
    for(int i=0;i<str.size();i++)
    {
        c=str[i]-a;
        j=ch[j][c];
        if(val[j]) print(j);
        else if(last[j]) print(last[j]);
    }
}
find的操作

print表示在确定一个串后的操作

bubuko.com,布布扣
void print(int j)
{
    if(j)
    {
        cnt[val[j]]++;
        print(last[j]);
    }
}
print的操作

整个自动机中,最重要的是后缀链接last数组的使用,对于一个单词的尾结点,可能对应多个串,需要沿着往回走,看看有没有串了。

 

@练习题

HDU 2222

HDU 2896

HDU 3065


AC自动机

标签:style   blog   http   color   os   使用   ar   for   sp   

原文地址:http://www.cnblogs.com/neopenx/p/4004407.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!