需要提前学习AC自动机的知识点:
大牛的AC自动机详解
HDU 2222 Keywords Search (传送门)
题意
求目标串中出现了几种模式串
解题思路
裸的 AC 自动机,使用一个标志模式串结尾的 end 数组,查询一次,将相应的 end 数组清零即可。
代码
/*头文件模板*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define pb push_back
#define mp make_pair
#define mem(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a))
#define lson rt << 1, l, mid
#define rson rt << 1|1, mid + 1, r
#define FIN freopen("input.txt", "r", stdin)
#define FOUT freopen("output.txt", "w", stdout)
typedef long long LL;
typedef pair<int, int > PII;
typedef pair<int, string> PIS;
typedef pairPLL;
typedef unsigned long long uLL;
template<typename T>
void print (T* p, T* q, string Gap = " ", bool flag = false) {
int d = p < q ? 1 : -1;
while (p != q) {
if (flag) cout << Gap[0] << *p << Gap[1];
else cout << *p;
p += d;
if (p != q && !flag) cout << Gap;
}
cout << endl;
}
template<typename T>
void print (const T &a, string bes = "") {
int len = bes.length();
if (len >= 2) cout << bes[0] << a << bes[1] << endl;
else cout << a << endl;
}
template<typename T>
void debug (T* p, T* q, string Gap = " ", bool flag = false) {
#ifndef ONLINE_JUDGE
int d = p < q ? 1 : -1;
cout << "Debug out : ";
while (p != q) {
if (flag) cout << Gap[0] << *p << Gap[1];
else cout << *p;
p += d;
if (p != q && !flag) cout << Gap;
}
cout << endl;
#endif
}
template<typename T>
void debug (const T &a, string bes = "") {
#ifndef ONLINE_JUDGE
int len = bes.length();
cout << "Debug out : ";
if (len >= 2) cout << bes[0] << a << bes[1] << endl;
else cout << a << endl;
#endif
}
void IO_Init() {
ios::sync_with_stdio (false);
}
LL LLabs (const LL a) {
return a >= 0 ? a : -a;
}
const double PI = 3.1415926535898;
const double eps = 1e-10;
const int MAXM = 1e5 + 5;
const int MAXN = 1e6 + 5;
const int INF = 0x3f3f3f3f;
/*头文件模板*/
struct AC {
struct node {
int end;
int next[27];
void init() {
end = 0;
mem(next, -1);
}
};
int tot, fail[MAXN];
node L[MAXN];
void init() {
tot = 0;
L[tot].init();
}
void insert(char buf[]) {
int slen = strlen(buf);
int now = 0;
for(int i = 0; i < slen; i ++) {
int tmp = buf[i] - 'a';
int next = L[now].next[tmp];
if(next == -1) {
next = ++ tot;
L[next].init();
L[now].next[tmp] = next;
}
now = next;
}
L[now].end ++;
}
void build() {
queue<int>Q;
int root = 0;
fail[root] = root;
for(int i = 0;i < 26;i ++){
if(L[root].next[i] == -1){
L[root].next[i] = root;
}
else{
fail[L[root].next[i]] = root;
Q.push(L[root].next[i]);
}
}
while(!Q.empty()){
int now = Q.front();
Q.pop();
for(int i = 0;i < 26;i ++){
if(L[now].next[i] == -1){
L[now].next[i] = L[fail[now]].next[i];
}
else{
fail[L[now].next[i]] = L[fail[now]].next[i];
Q.push(L[now].next[i]);
}
}
}
}
int query(char buf[]){
int slen = strlen(buf);
int now = 0, res = 0;
for(int i = 0;i < slen;i ++){
int tmp = buf[i] - 'a';
int p = L[now].next[tmp];
now = p;
while(p){
res += L[p].end;
L[p].end = 0;
p = fail[p];
}
}
return res;
}
};
int T, n;
char buf[MAXN];
AC ac;
int main() {
#ifndef ONLINE_JUDGE
//FIN;
//FOUT;
#endif
IO_Init();
scanf("%d", &T);
while(T --){
ac.init();
scanf("%d", &n);
for(int i = 0;i < n;i ++){
scanf("%s", buf);
ac.insert(buf);
}
ac.build();
scanf("%s", buf);
printf("%d\n", ac.query(buf));
}
return 0;
}
HDU 2896 病毒侵袭 (传送门)
题意
输出出现模式串的 id 和有模式串的字符串的个数
解题思路
用 end 记录 id 就可以了,同时注意 [ 以上字符串中字符都是ASCII码可见字符] ,所以字典树最少需要开 128 大小的数组.
代码
/*头文件模板*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define pb push_back
#define mp make_pair
#define mem(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a))
#define lson rt << 1, l, mid
#define rson rt << 1|1, mid + 1, r
#define FIN freopen("input.txt", "r", stdin)
#define FOUT freopen("output.txt", "w", stdout)
typedef long long LL;
typedef pair<int, int > PII;
typedef pair<int, string> PIS;
typedef pairPLL;
typedef unsigned long long uLL;
template<typename T>
void print (T* p, T* q, string Gap = " ", bool flag = false) {
int d = p < q ? 1 : -1;
while (p != q) {
if (flag) cout << Gap[0] << *p << Gap[1];
else cout << *p;
p += d;
if (p != q && !flag) cout << Gap;
}
cout << endl;
}
template<typename T>
void print (const T &a, string bes = "") {
int len = bes.length();
if (len >= 2) cout << bes[0] << a << bes[1] << endl;
else cout << a << endl;
}
template<typename T>
void debug (T* p, T* q, string Gap = " ", bool flag = false) {
#ifndef ONLINE_JUDGE
int d = p < q ? 1 : -1;
cout << "Debug out : ";
while (p != q) {
if (flag) cout << Gap[0] << *p << Gap[1];
else cout << *p;
p += d;
if (p != q && !flag) cout << Gap;
}
cout << endl;
#endif
}
template<typename T>
void debug (const T &a, string bes = "") {
#ifndef ONLINE_JUDGE
int len = bes.length();
cout << "Debug out : ";
if (len >= 2) cout << bes[0] << a << bes[1] << endl;
else cout << a << endl;
#endif
}
void IO_Init() {
ios::sync_with_stdio (false);
}
LL LLabs (const LL a) {
return a >= 0 ? a : -a;
}
const double PI = 3.1415926535898;
const double eps = 1e-10;
const int MAXM = 1e5 + 5;
const int MAXN = 1e5 + 5;
const int INF = 0x3f3f3f3f;
/*头文件模板*/
struct AC {
struct node {
int end;
int next[128];
void init() {
end = 0;
mem(next, -1);
}
};
int tot, fail[MAXN];
node L[MAXN];
void init() {
tot = 0;
L[0].init();
mem(fail, 0);
}
void insert(char buf[], int d) {
int slen = strlen(buf);
int now = 0;
for(int i = 0; i < slen; i ++) {
int tmp = buf[i];
int next = L[now].next[tmp];
if(next == -1) {
next = ++ tot;
L[next].init();
L[now].next[tmp] = next;
}
now = next;
}
L[now].end = d;
}
void build() {
queue<int>Q;
int root = 0;
fail[root] = root;
for(int i = 0; i < 128; i ++) {
if(L[root].next[i] == -1) {
L[root].next[i] = root;
} else {
fail[L[root].next[i]] = root;
Q.push(L[root].next[i]);
}
}
while(!Q.empty()) {
int now = Q.front();
Q.pop();
for(int i = 0; i < 128; i ++) {
if(L[now].next[i] == -1) {
L[now].next[i] = L[fail[now]].next[i];
} else {
fail[L[now].next[i]] = L[fail[now]].next[i];
Q.push(L[now].next[i]);
}
}
}
}
vector<int> query(char buf[]) {
vector<int>V;
int slen = strlen(buf);
int now = 0;
for(int i = 0;i < slen;i ++){
int tmp = buf[i];
int p = L[now].next[tmp];
now = p;
while(p){
if(L[p].end != 0) V.pb(L[p].end);
p = fail[p];
}
}
sort(V.begin(), V.end());
V.erase(unique(V.begin(), V.end()), V.end());
return V;
}
} ac;
int N, M;
char bd[MAXN], web[MAXN];
int main() {
#ifndef ONLINE_JUDGE
//FIN;
//FOUT;
#endif
IO_Init();
ac.init();
scanf("%d", &N);
for(int i = 1; i <= N; i ++) {
scanf("%s", bd);
ac.insert(bd, i);
}
ac.build();
scanf("%d", &M);
vector<int>bV;
int ans = 0;
for(int i = 1; i <= M; i ++) {
scanf("%s", web);
bV = ac.query(web);
if(bV.size() > 0) {
ans ++;
printf("web %d:", i);
for(int j = 0; j < bV.size(); j ++) {
printf(" %d", bV[j]);
}
printf("\n");
}
}
printf("total: %d\n", ans);
return 0;
}
HDU 3065 病毒侵袭持续中(传送门)
题意
输出每个模式串出现的次数
解题思路
直接用数组记录一下就可以了, [ 题目有一丢丢小问题,要多组输入]
代码
/*头文件模板*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
#define pb push_back
#define mp make_pair
#define mem(a, x) memset(a, x, sizeof(a))
#define copy(a, b) memcpy(a, b, sizeof(a))
#define lson rt << 1, l, mid
#define rson rt << 1|1, mid + 1, r
#define FIN freopen("input.txt", "r", stdin)
#define FOUT freopen("output.txt", "w", stdout)
typedef long long LL;
typedef pair<int, int > PII;
typedef pair<int, string> PIS;
typedef pairPLL;
typedef unsigned long long uLL;
template<typename T>
void print (T* p, T* q, string Gap = " ", bool flag = false) {
int d = p < q ? 1 : -1;
while (p != q) {
if (flag) cout << Gap[0] << *p << Gap[1];
else cout << *p;
p += d;
if (p != q && !flag) cout << Gap;
}
cout << endl;
}
template<typename T>
void print (const T &a, string bes = "") {
int len = bes.length();
if (len >= 2) cout << bes[0] << a << bes[1] << endl;
else cout << a << endl;
}
template<typename T>
void debug (T* p, T* q, string Gap = " ", bool flag = false) {
#ifndef ONLINE_JUDGE
int d = p < q ? 1 : -1;
cout << "Debug out : ";
while (p != q) {
if (flag) cout << Gap[0] << *p << Gap[1];
else cout << *p;
p += d;
if (p != q && !flag) cout << Gap;
}
cout << endl;
#endif
}
template<typename T>
void debug (const T &a, string bes = "") {
#ifndef ONLINE_JUDGE
int len = bes.length();
cout << "Debug out : ";
if (len >= 2) cout << bes[0] << a << bes[1] << endl;
else cout << a << endl;
#endif
}
void IO_Init() {
ios::sync_with_stdio (false);
}
LL LLabs (const LL a) {
return a >= 0 ? a : -a;
}
const double PI = 3.1415926535898;
const double eps = 1e-10;
const int MAXM = 1e5 + 5;
const int MAXN = 1e6 + 5;
const int INF = 0x3f3f3f3f;
/*头文件模板*/
struct AC {
struct node {
int end;
int next[128];
void init() {
end = 0;
mem(next, -1);
}
};
int tot, fail[MAXN];
node L[MAXN];
void init() {
tot = 0;
L[0].init();
mem(fail, 0);
}
void insert(char buf[], int d) {
int slen = strlen(buf);
int now = 0;
for(int i = 0; i < slen; i ++) {
int tmp = buf[i];
int next = L[now].next[tmp];
if(next == -1) {
next = ++ tot;
L[next].init();
L[now].next[tmp] = next;
}
now = next;
}
L[now].end = d;
}
void build() {
queue<int>Q;
int root = 0;
fail[root] = root;
for(int i = 0; i < 128; i ++) {
if(L[root].next[i] == -1) {
L[root].next[i] = root;
} else {
fail[L[root].next[i]] = root;
Q.push(L[root].next[i]);
}
}
while(!Q.empty()) {
int now = Q.front();
Q.pop();
for(int i = 0; i < 128; i ++) {
if(L[now].next[i] == -1) {
L[now].next[i] = L[fail[now]].next[i];
} else {
fail[L[now].next[i]] = L[fail[now]].next[i];
Q.push(L[now].next[i]);
}
}
}
}
void query(char buf [], int K[]) {
int slen = strlen(buf);
int now = 0;
for(int i = 0; i < slen; i ++) {
int tmp = buf[i];
int p = L[now].next[tmp];
now = p;
while(p) {
K[L[p].end] ++;
p = fail[p];
}
}
}
} ac;
int N, M;
char bd[60], web[MAXN << 1];
string T1[1000 + 5];
int Vnum[1000 + 5];
int main() {
#ifndef ONLINE_JUDGE
//FIN;
//FOUT;
#endif
IO_Init();
while(~scanf("%d", &N)) {
ac.init();
mem(Vnum, 0);
for(int i = 1; i <= N; i ++) {
scanf("%s", bd);
T1[i] = string(bd);
ac.insert(bd, i);
}
ac.build();
scanf("%s", web);
ac.query(web, Vnum);
for(int i = 1; i <= N; i ++) {
if(Vnum[i] > 0) {
cout << T1[i] << ": " << Vnum[i] << endl;
}
}
}
return 0;
}