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;
}
AC自动机算法解析
1737

被折叠的 条评论
为什么被折叠?



