ac自动机
题目链接:
ac自动机的精华在于 \(fail\) 指针,
为了避免暴力跳 \(fail\) 指针使得复杂度爆炸,建出 \(fail\) 图就好了
P3808
https://www.luogu.com.cn/problem/P3808
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 1000010;
int n, rt = 0, tot = 0;
ll ans = 0;
struct Node{
int son[30], sz, fail;
}t[maxn];
char s[maxn];
void insert(){
int p = rt;
int len = strlen(s);
for(int i = 0 ; i < len ; ++i){
if(!t[p].son[s[i] - 'a']){
t[p].son[s[i] - 'a'] = ++tot;
}
p = t[p].son[s[i] - 'a'];
}
++t[p].sz;
}
queue<int> q;
void build(){
t[rt].fail = rt;
for(int i = 0 ; i <= 25 ; ++i){
if(t[rt].son[i]) q.push(t[rt].son[i]);
}
while(!q.empty()){
int u = q.front(); q.pop();
for(int i = 0 ; i <= 25 ; ++i){
if(t[u].son[i]){
t[t[u].son[i]].fail = t[t[u].fail].son[i];
q.push(t[u].son[i]);
} else{
t[u].son[i] = t[t[u].fail].son[i];
}
}
}
}
void query(){
int p = rt;
int len = strlen(s);
for(int i = 0 ; i < len ; ++i){
p = t[p].son[s[i] - 'a'];
for(int j = p ; j && ~t[j].sz ; j = t[j].fail) ans += t[j].sz, t[j].sz = -1;
}
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
n = read();
for(int i = 1 ; i <= n ; ++i){
scanf("%s", s);
insert();
}
build();
scanf("%s", s);
query();
printf("%lld\n", ans);
return 0;
}
P3796
https://www.luogu.com.cn/problem/P3796
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 20010;
int n, rt = 0, tot = 0;
int ans[maxn], c[maxn], mx;
struct Node{
int son[30], en, fail;
}t[maxn];
char s[200][100];
char txt[1000010];
void insert(int num){
int p = rt;
int len = strlen(s[num]);
for(int i = 0 ; i < len ; ++i){
if(!t[p].son[s[num][i] - 'a']){
t[p].son[s[num][i] - 'a'] = ++tot;
}
p = t[p].son[s[num][i] - 'a'];
}
t[p].en = tot;
c[num] = tot;
}
void build(){
queue<int> q;
t[rt].fail = rt;
for(int i = 0 ; i <= 25 ; ++i){
if(t[rt].son[i]) q.push(t[rt].son[i]);
}
while(!q.empty()){
int u = q.front(); q.pop();
for(int i = 0 ; i <= 25 ; ++i){
if(t[u].son[i]){
t[t[u].son[i]].fail = t[t[u].fail].son[i];
q.push(t[u].son[i]);
} else{
t[u].son[i] = t[t[u].fail].son[i];
}
}
}
}
void query(){
int p = rt;
int len = strlen(txt);
for(int i = 0 ; i < len ; ++i){
p = t[p].son[txt[i] - 'a'];
for(int j = p ; j ; j = t[j].fail) {
++ans[t[j].en];
if(t[j].en) mx = max(mx, ans[t[j].en]);
}
}
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
while(1){
memset(t, 0, sizeof(t));
memset(ans, 0, sizeof(ans));
memset(c, 0, sizeof(c));
mx = 0; tot = 0;
n = read();
if(!n) break;
for(int i = 1 ; i <= n ; ++i){
scanf("%s", s[i]);
insert(i);
}
build();
scanf("%s", txt);
query();
printf("%d\n", mx);
for(int i = 1 ; i <= n ; ++i){
if(ans[c[i]] == mx) printf("%s\n", s[i]);
}
}
return 0;
}
P5357 https://www.luogu.com.cn/problem/P5357
\(fail\) 树上差分
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn = 200010;
int n, rt = 0, tot = 0;
int ans[maxn], c[maxn], mx;
struct Node{
int son[30], en, fail;
}t[maxn];
int h[maxn], cnt = 0;
struct E{
int to, next;
}e[maxn << 1];
void add(int u, int v){
e[++cnt].to = v;
e[cnt].next = h[u];
h[u] = cnt;
}
char s[2000010];
char txt[2000010];
void insert(int num){
int p = rt;
int len = strlen(s);
for(int i = 0 ; i < len ; ++i){
if(!t[p].son[s[i] - 'a']){
t[p].son[s[i] - 'a'] = ++tot;
}
p = t[p].son[s[i] - 'a'];
}
t[p].en = p;
c[num] = p;
}
void build(){
queue<int> q;
t[rt].fail = rt;
for(int i = 0 ; i <= 25 ; ++i){
if(t[rt].son[i]) {
add(rt, t[rt].son[i]);
q.push(t[rt].son[i]);
}
}
while(!q.empty()){
int u = q.front(); q.pop();
for(int i = 0 ; i <= 25 ; ++i){
if(t[u].son[i]){
t[t[u].son[i]].fail = t[t[u].fail].son[i];
add(t[u].son[i], t[t[u].son[i]].fail);
add(t[t[u].son[i]].fail, t[u].son[i]);
q.push(t[u].son[i]);
} else{
t[u].son[i] = t[t[u].fail].son[i];
}
}
}
}
int d[maxn];
void query(){
int p = rt;
int len = strlen(txt);
for(int i = 0 ; i < len ; ++i){
p = t[p].son[txt[i] - 'a'];
++d[p];
// printf("%d ", p);
}
}
void dfs(int u, int par){
// printf("%d ", u);
for(int i = h[u] ; i != -1 ; i = e[i].next){
int v = e[i].to;
if(v == par) continue;
dfs(v, u);
d[u] += d[v];
}
}
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
while(scanf("%d", &n) != EOF){
memset(h, -1, sizeof(h));
memset(t, 0, sizeof(t));
memset(ans, 0, sizeof(ans));
memset(c, 0, sizeof(c));
mx = 0; tot = 0;
for(int i = 1 ; i <= n ; ++i){
scanf("%s", s);
insert(i);
}
build();
scanf("%s", txt);
query();
// printf("\n");
dfs(0, 0);
// printf("\n");
for(int i = 1 ; i <= n ; ++i){
printf("%d\n", d[c[i]]);
}
}
return 0;
}