AC自动机

AC自动机算法解析

AC自动机可不是,帮你AC的机器,而是字符串的匹配,它主要用来解决什么类型的问题呢?主要用来解决一个主串和多个子串之间进行匹配的问题。

参考博客:AC自动机 算法详解(图解)及模板

例题1:P3808 【模板】AC自动机(简单版)

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e6+7;

int trie[maxn][26];
int word[maxn];
int fail[maxn];
int cnt = 0;
void InsertWord(string s){
     int root = 0;
     for(int i = 0; i < s.size(); i++){
        int next = s[i] - 'a';
        if(!trie[root][next]){
            trie[root][next] = ++cnt;
        }
        root = trie[root][next];
     }
     word[root]++;
}
void getFail(){
     queue<int>q;
     for(int i = 0; i < 26; i++){
        if(trie[0][i]){
            fail[trie[0][i]] = 0;
            q.push(trie[0][i]);
        }
     }
     while(!q.empty()){
          int now = q.front();
          q.pop();
          for(int i = 0; i < 26; i++){
            if(trie[now][i]){
                fail[trie[now][i]] = trie[fail[now]][i];
                q.push(trie[now][i]);
            }
            else trie[now][i] = trie[fail[now]][i];
          }
     }
}
int query(string s){
    int now = 0, ans = 0;
    for(int i = 0; i < s.size(); i++){
        now = trie[now][s[i]-'a'];
        for(int j = now; j  && word[j] != -1; j = fail[j]){
            ans += word[j];
            word[j] = -1;
        }
    }
    return ans;
}
int main(){
    ios::sync_with_stdio(false);
    int n;
    string a, s;
    cin>>n;
    for(int i = 1; i <= n; i++){
        cin>>a;
        InsertWord(a);
    }
    fail[0] = 0;
    getFail();
    cin>>s;
    cout<<query(s)<<endl;
return 0;
}

例题2:P3796 【模板】AC自动机(加强版)

代码:

#include<bits/stdc++.h>
using namespace std;
const int maxn = 100000;
struct Node
{
    int id, cn;
} re[maxn];
string a[200];
int trie[maxn][26];
int word[maxn];
int fail[maxn];
int cnt = 0;
map<int, int>mp;//映射到是哪一个串
void InsertWord(string s, int i)
{
    int root = 0;
    for(int i = 0; i < s.size(); i++)
    {
        int next = s[i] - 'a';
        if(!trie[root][next])
        {
            trie[root][next] = ++cnt;
        }
        root = trie[root][next];
    }
    word[root]++;
    mp[root] = i;
}
void getFail()
{
    queue<int>q;
    for(int i = 0; i < 26; i++)
    {
        if(trie[0][i])
        {
            fail[trie[0][i]] = 0;
            q.push(trie[0][i]);
        }
    }
    while(!q.empty())
    {
        int now = q.front();
        q.pop();
        for(int i = 0; i < 26; i++)
        {
            if(trie[now][i])
            {
                fail[trie[now][i]] = trie[fail[now]][i];
                q.push(trie[now][i]);
            }
            else trie[now][i] = trie[fail[now]][i];
        }
    }
}
void query(string s)
{
    int now = 0, ans = 0;
    for(int i = 0; i < s.size(); i++)
    {
        now = trie[now][s[i]-'a'];
        for(int j = now; j; j = fail[j])
        {
            if(word[j])
            {
                int t = mp[j];
                re[t].id = t;
                re[t].cn++;
            }

        }
    }
}
bool cmp(Node A, Node B)
{
    if(A.cn == B.cn)
    {
        return A.id < B.id;
    }
    else return A.cn > B.cn;
}
void init(){//初始化
     cnt = 0;
     memset(word, 0, sizeof(word));
     memset(re, 0, sizeof(re));
     memset(fail, 0, sizeof(fail));
     memset(trie, 0, sizeof(trie));
}
int main()
{
    ios::sync_with_stdio(false);
    int n;
    string s;
    while(cin>>n && n != 0)
    {

        init();
        for(int i = 1; i <= n; i++)
        {
            cin>>a[i];
            InsertWord(a[i], i);
        }
        fail[0] = 0;
        cin>>s;
        getFail();
        query(s);
        sort(re+1, re+1+n, cmp);
        int ans = re[1].cn;
        cout<<ans<<endl;
        for(int i = 1; i <= n; i++)
        {
            if(re[i].cn == ans)
            {
                cout<<a[re[i].id]<<endl;
            }
            else break;
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值