struct Aho{
struct node{
int next[26];
int fail,cnt;
}state[maxn];
queue<int> q;
int size;
int idx(char ch) {return ch - 'a';}
void init(){
while(!q.empty()) q.pop();
for(int i=0; i<maxn; i++){
memset(state[i].next, 0, sizeof(state[i].next));
state[i].fail = state[i].cnt = 0;
}
size = 1;
}
void insert(char *s){
int n = (int)strlen(s);
int now = 0;
for(int i=0; i<n; i++){
int c = idx(s[i]);
if(!state[now].next[c]){
state[now].next[c] = size++;
}
now = state[now].next[c];
}
vec[now].push_back(id);
state[now].cnt++;
}
void build(){
state[0].fail = -1;
q.push(0);//0是根节点
while(!q.empty()){
int u = q.front();
q.pop();
for(int i=0; i<26; i++){
if(state[u].next[i]){
if(u == 0) state[state[u].next[i]].fail = 0;
else{
int v = state[u].fail;//父亲的fail
while(v != -1){
if(state[v].next[i]){//如果该节点的儿子有这条边
state[state[u].next[i]].fail = state[v].next[i];
break;
}
v = state[v].fail;
}
if(v == -1)
state[state[u].next[i]].fail = 0;
}
q.push(state[u].next[i]);
}
else{//按照蓝书上的话说 是把不存在的fail也补上 导致match时可以不需要不断往上跳
if(u == 0) state[u].next[i] = 0;
else state[u].next[i] = state[state[u].fail].next[i];
}
}
}
}
int get(int now){
int ans = 0;
while(now){
ans += state[now].cnt;
state[now].cnt = 0;
now = state[now].fail;
}
return ans;
}
int match(char *s){
int n = (int)strlen(s);
int now = 0;
int ans = 0;
for(int i=0; i<n; i++){
int c = idx(s[i]);
if(state[now].next[c])
now = state[now].next[c];
else{
int p = state[now].fail;
while(p != -1 && state[p].next[c] == 0) p = state[p].fail;
if(p == -1) now = 0;
else now = state[p].next[c];
}
ans += get(now);
}
return ans;
}
}aho;