AC自动机来袭!!!

AC自动机——无法自动AC的数据结构,trie树与字符串的结合,用于以多组数据匹配一种数据;

int tr[N*M][26],idx;
int ne[N*M];
int cnt[N*M];
int q[N*M];

tr数组是trie树数组,ne数组是kmp的next数组,cnt数组则记录trie树中对应位置的字符串出现了多少次,

q数组为队列

void insert(string s)
{
    int p=0;
    for(int i=0;i<s.size();i++)
    {
        int t=s[i]-'a';
        if(!tr[p][t]) tr[p][t]=++idx;
        p=tr[p][t];
    }
    cnt[p]++;
}

建树过程与trie树相同

void build()//一层层bfs构建ne数组
{
    int hh=0,tt=-1;
    for(int i=0;i<26;i++)
    if(tr[0][i]) q[++tt]=tr[0][i];
    while(hh<=tt)
    {
        int t=q[hh++];
        for(int i=0;i<26;i++)
        {
            int c=tr[t][i];
            if(!c) tr[t][i]=tr[ne[t]][i];//把不存在的点连起来使得求ne数组不再需要一层层往上循环
            else   
            {
            ne[c]=tr[ne[t]][i];
            q[++tt]=c;
            }
        }
    }
}

建立ne数组的过程,为一层一层bfs,这里优化了一下成为了trie图

 for(int i=0,j=0;i<s1.size();i++)
        {
            int t=s1[i]-'a';
            j=tr[j][t];
            int p=j;
            while(p)
            {
                res+=cnt[p]; cnt[p]=0;p=ne[p];
            }
        }

匹配的时候注意回溯,否则可能会漏,这里其实还可以加一个st数组防止重复匹配

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值