struct AC_automation {
int L;
int next[maxnode][sigma_size];
int val[maxnode];
int fail[maxnode], last[maxnode];
int newnode()
{
memset(next[L],0,sizeof(next[L]));
fail[L] = last[L] = val[L] = 0;
return L++;
} //新建结点
void init() {
memset(next[0], 0, sizeof(next[0]));
fail[0] = last[0] = val[0] = 0;
L = 1;
}// 初始化
inline int idx(char c) {
return c - '0';
}
int insert(const char *str) {
int len = strlen(str), u = 0;
for(int i = 0; i < len; i++) {
int c = idx(str[i]);
if(next[u][c] == 0) {
memset(next[L], 0, sizeof(next[L]));
fail[L] = last[L] = val[L] = 0;
next[u][c] = L++;
}
u = next[u][c];
}
int ret = val[u];
val[u] = 1;
return !ret;
}// 插入字典树
bool ask(const char *str) {
int len = strlen(str), u = 0;
for(int i = 0; i < len; i++) {
int c = idx(str[i]);
if(next[u][c] == 0) return false;
u = next[u][c];
}
return val[u];
} // 存不存在
void build() {
std::queue<int> q;
int u = 0;
fail[0] = 0;
for(int c = 0; c < sigma_size; c++) {
int u = next[0][c];
if(u) { fail[u] = last[u] = 0; q.push(u); }
}
while(!q.empty()) {
int r = q.front(); q.pop();
for(int c = 0; c < sigma_size; c++) {
int u = next[r][c];
if(!u) continue;
q.push(u);
int v = fail[r];
while(v && !next[v][c]) v = fail[v];
fail[u] = next[v][c];
last[u] = val[fail[u]] ? fail[u] : last[fail[u]];
}
}
}//get-fail
void calc(int now, int &ans) {
if(now) {
ans += val[now];
calc(last[now], ans);
}
}
int query(char *str) {
//printf("query %s\n", str);
int len = strlen(str), u = 0;
int ans = 0;
for(int i = 0; i < len; i++) {
int c = idx(str[i]);
while(u && !next[u][c]) u = fail[u];
u = next[u][c];
if(val[u]) calc(u, ans);
else if(last[u]) calc(last[u], ans);
}
return ans;
}// 查询出现次数
}ac1,ac2;