关于AC自动机,http://www.cnblogs.com/kuangbin/p/3164106.html这个博客讲的非常清楚。
AC自动机基本就是trie和kmp的结合,实现起来也没有特别麻烦的细节,比kmp甚至还好写。关于next数组和fail数组,fail数组就是kmp中的next数组,只不过fail数组是针对很多组字符串而kmp中的next只有一个字符串。AC自动机中的fail数组在查询过程中完全没有用到,查询用到的是一个next数组,next[now][buf[i]]就是指在当前匹配是now的情况下,下一个字符是buf[i]的最佳匹配。
HDU 2222
#include <iostream>
#include <queue>
#include <cstring>
#include <string>
#include <cstdio>
using namespace std;
int n;
const int N = 10010;
class AC_auto
{
public:
int next[N*52][26],fail[N*52],end[N*52];
int root,L;
int newnode()
{
for (int i = 0; i < 26; i++)
{
next[L][i] = -1;
}
end[L++] = 0;
return L-1;
}
void init()
{
L = 0;
root = newnode();
}
void insert(char buf[])
{
int now = root;
int len = strlen(buf);
for (int i = 0 ; i < len; i++)
{
int w = buf[i]-'a';
if (next[now][w] == -1)
{
next[now][w] = newnode();
}
now = next[now][w];
}
end[now] += 1;
}
void build()
{
queue<int> Q;
fail[root] = root;
for (int i =0; i < 26; i++)
{
if (next[root][i] == -1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
}
while (!Q.empty())
{
int now = Q.front();
Q.pop();
for(int i = 0; i < 26; i++)
{
if (next[now][i] == -1)
{
next[now][i] = next[fail[now]][i];
}
else
{
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
int query(char buf[])
{
int ans = 0;
int now = root;
int len = strlen(buf);
for(int i = 0; i < len; i++)
{
int w = buf[i] - 'a';
now = next[now][w];
int temp = now;
while (temp != root)
{
ans += end[temp];
end[temp] = 0;
temp = fail[temp];
}
}
return ans;
}
};
AC_auto a;
void solve()
{
int m;
scanf("%d",&m);
a.init();
char buf[100];
char target[1001000];
for (int i = 0; i < m; i++)
{
scanf("%s",buf);
a.insert(buf);
}
a.build();
scanf("%s",target);
printf("%d\n",a.query(target));
}
int main()
{
scanf("%d",&n);
for (int i = 0; i < n; i++)
{
solve();
}
return 0;
}
HDU 2896
#include <iostream>
#include <queue>
#include <cstring>
#include <vector>
#include <algorithm>
#include <cstdio>
using namespace std;
const int N = 100000;
class AC_auto
{
public:
int next[N*10][128],end[N*52],fail[N*52];
int root,L;
int newnode()
{
for (int i = 0; i < 128; i++)
{
next[L][i] = -1;
}
end[L++] = 0;
return L -1;
}
void init()
{
L = 0;
root = newnode();
}
void insert(char buf[],int k)
{
int len = strlen(buf);
int now = root;
for (int i = 0 ; i < len; i++)
{
int w = buf[i];
if (next[now][w] == -1)
{
next[now][w] = newnode();
}
now = next[now][w];
}
end[now] = k;
}
void build()
{
queue<int> Q;
fail[root] = root;
for (int i = 0; i < 128; i++)
{
if (next[root][i] == -1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
}
while (!Q.empty())
{
int now = Q.front();
Q.pop();
for(int i = 0; i < 128; i++)
{
if (next[now][i] == -1)
{
next[now][i] = next[fail[now]][i];
}else
{
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
vector<int> *query(char buf[],vector<int>* a)
{
a->clear();
int now = root;
int len = strlen(buf);
for (int i = 0; i < len; i++)
{
int w = buf[i];
now = next[now][w];
int temp = now;
while(temp != root)
{
if (end[temp] != 0)
{
a->push_back(end[temp]);
}
temp = fail[temp];
}
}
return a;
}
};
AC_auto ac;
int n;
int m;
void init()
{
scanf("%d",&n);
ac.init();
char buf[300];
for (int i = 0; i < n; i++)
{
scanf("%s",buf);
ac.insert(buf,i+1);
}
ac.build();
}
void solve()
{
scanf("%d",&m);
char buf[11000];
vector<int> a;
int sum = 0;
for (int i = 1; i <= m ;i++)
{
scanf("%s",buf);
ac.query(buf,&a);
sort(a.begin(),a.end());
if (a.size() == 0)
continue;
printf("web %d:",i);
sum++;
for (int j = 0; j < a.size(); j++)
{
if (j == 0 || a[j] != a[j-1])
{
printf(" %d",a[j]);
}
}
printf("\n");
}
printf("total: %d\n",sum);
}
int main()
{
init();
solve();
return 0;
}
HDU 3065
#include <iostream>
#include <memory.h>
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 60000;
class AC_auto
{
public:
int next[N][26],end[N],d[N],fail[N];
int root,L;
int newnode()
{
for(int i = 0; i< 26; i++)
next[L][i] = -1;
end[L] = 0;
L++;
return L-1;
}
void init()
{
L = 0;
root = newnode();
memset(d,0,sizeof(d));
}
void insert(char buf[],int k)
{
int now = root;
int len = strlen(buf);
for(int i = 0; i < len; i++)
{
int w = buf[i]-'A';
if (next[now][w] == -1)
{
next[now][w] = newnode();
}
now = next[now][w];
}
end[now] = k;
}
void build()
{
queue<int> Q;
fail[root] = root;
for(int i = 0; i < 26;i++)
{
if (next[root][i] == -1)
next[root][i] = root;
else
{
fail[next[root][i]] = root;
Q.push(next[root][i]);
}
}
while (!Q.empty())
{
int now = Q.front();
Q.pop();
for (int i = 0; i < 26; i++)
{
if (next[now][i] == -1)
{
next[now][i] = next[fail[now]][i];
}
else
{
fail[next[now][i]] = next[fail[now]][i];
Q.push(next[now][i]);
}
}
}
}
void query(char buf[])
{
int len = strlen(buf);
int now = root;
for(int i = 0; i < len; i++)
{
if (buf[i] >= 'A' && buf[i] <= 'Z')
{
int w = buf[i] - 'A';
now = next[now][w];
}else
now = root;
int temp = now;
while (temp != root)
{
if (end[temp])
{
d[end[temp]]++;
}
temp = fail[temp];
}
}
}
};
vector<string> s;
int n;
AC_auto ac;
char buf[2100000];
void init()
{
char buf[100];
ac.init();
s.clear();
for (int i = 0; i < n; i++)
{
scanf("%s",buf);
ac.insert(buf,i+1);
s.push_back(string(buf));
}
ac.build();
}
void solve()
{
scanf("%s",buf);
ac.query(buf);
for (int i = 0; i < n; i++)
{
if (ac.d[i+1])
{
printf("%s: %d\n",s[i].c_str(),ac.d[i+1]);
}
}
}
int main()
{
while (scanf("%d",&n) != EOF){
init();
solve();
}
return 0;
}