原理看这:
写的真的很好啦orz
模板:
普通AC自动机
void insert(char s[]){
int u = 0;
for(int i = 0;s[i];i ++){
int v = s[i] - 'a';
if(!ch[u][v]) ch[u][v] = ++ cnt;
u = ch[u][v];
}
}
void getfail(){
queue<int> q;
for(int i = 0;i < 26;i ++) if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty()){
int u = q.front();q.pop();
for(int i = 0;i < 26;i ++){
if(ch[u][i]){
fail[ch[u][i]] = ch[fail[u]][i];
q.push(ch[u][i]);
}
else ch[u][i] = ch[fail[u]][i];
}
}
}
void query(char s[]){
int u = 0;
for(int i = 0;s[i];i ++){
u = ch[u][s[i] - 'a'];
for(int j = u;j;j = fail[j]) ...
}
}
fail树优化(求每个模式串在主串中的出现次数)
void insert(char s[],int x){
int u = 0;
for(int i = 0;s[i];i ++){
int v = s[i] - 'a';
if(!ch[u][v]) ch[u][v] = ++ cnt;
u = ch[u][v];
}
fl[x] = u;
}
void getfail(){
queue<int> q;
for(int i = 0;i < 26;i ++) if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty()){
int u = q.front();q.pop();
for(int i = 0;i < 26;i ++){
if(ch[u][i]){
fail[ch[u][i]] = ch[fail[u]][i];
q.push(ch[u][i]);
}
else ch[u][i] = ch[fail[u]][i];
}
}
}
void query(char s[]){
int u = 0;
for(int i = 0;s[i];i ++){
u = ch[u][s[i] - 'a'];
sum[u] ++;
}
}
void add(int u,int v){
e[++ tot].next = head[u];
head[u] = tot;
e[tot].to = v;
}
void dfs(int u){
for(int i = head[u];i;i = e[i].next){
int v = e[i].to;
dfs(v);
sum[u] += sum[v];
}
}