template<int maxnode,int sigma_size>
struct Aho_Corasick{
int ch[maxnode][sigma_size];
int val[maxnode],last[maxnode],f[maxnode];
int sz;
//int cnt[maxnode];
//bool mark[maxnode];
Aho_Corasick() {
sz=1;
memset(ch[0],0,sizeof(ch[0]));
}
int idx(char c) {
return c-'a';
}
void init() {
sz=1;
memset(ch[0],0,sizeof(ch[0]));
// memset(cnt,0,sizeof(cnt));
//memset(mark,0,sizeof(mark));
}
void insert(char *s,int v) {
int u=0,n=strlen(s);
for(int i=0;i<n;i++) {
int c=idx(s[i]);
if(!ch[u][c]) {
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=v;
cnt[u]++;
}
int find(char *T) {
int ans=0;
int n=strlen(T);
int j=0;
for(int i=0;i<n;i++) {
int c=idx(T[i]);
while(j && !ch[j][c]) j=f[j];
j=ch[j][c];
if(val[j]) print(j,ans);
else print(last[j],ans);
//printf("FF %d %d\n",i,ans);
}
return ans;
}
void print(int j,int &ans) {
if(j && !mark[j]) {
ans+=cnt[j];
mark[j]=1;
print(last[j],ans);
}
}
void getFail() {
queue<int>q;
f[0]=0;
last[0]=0;
for(int c=0;c<sigma_size;c++) {
int u=ch[0][c];
if(u) {
f[u]=0;q.push(u);last[u]=0;
}
}
while(!q.empty()) {
int r=q.front();q.pop();
for(int c=0;c<sigma_size;c++) {
int u=ch[r][c];
if(!u) { ch[r][c]=ch[f[r]][c]; continue; }
q.push(u);
int v=f[r];
while(v && !ch[v][c]) v=f[v];
f[u]=ch[v][c];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
};
struct Aho_Corasick{
int ch[maxnode][sigma_size];
int val[maxnode],last[maxnode],f[maxnode];
int sz;
//int cnt[maxnode];
//bool mark[maxnode];
Aho_Corasick() {
sz=1;
memset(ch[0],0,sizeof(ch[0]));
}
int idx(char c) {
return c-'a';
}
void init() {
sz=1;
memset(ch[0],0,sizeof(ch[0]));
// memset(cnt,0,sizeof(cnt));
//memset(mark,0,sizeof(mark));
}
void insert(char *s,int v) {
int u=0,n=strlen(s);
for(int i=0;i<n;i++) {
int c=idx(s[i]);
if(!ch[u][c]) {
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=v;
cnt[u]++;
}
int find(char *T) {
int ans=0;
int n=strlen(T);
int j=0;
for(int i=0;i<n;i++) {
int c=idx(T[i]);
while(j && !ch[j][c]) j=f[j];
j=ch[j][c];
if(val[j]) print(j,ans);
else print(last[j],ans);
//printf("FF %d %d\n",i,ans);
}
return ans;
}
void print(int j,int &ans) {
if(j && !mark[j]) {
ans+=cnt[j];
mark[j]=1;
print(last[j],ans);
}
}
void getFail() {
queue<int>q;
f[0]=0;
last[0]=0;
for(int c=0;c<sigma_size;c++) {
int u=ch[0][c];
if(u) {
f[u]=0;q.push(u);last[u]=0;
}
}
while(!q.empty()) {
int r=q.front();q.pop();
for(int c=0;c<sigma_size;c++) {
int u=ch[r][c];
if(!u) { ch[r][c]=ch[f[r]][c]; continue; }
q.push(u);
int v=f[r];
while(v && !ch[v][c]) v=f[v];
f[u]=ch[v][c];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
};