constint N =1e6+5;int trie[N][26];// 字典树int wordcnt[N];// 次数统计int fail[N];// 众所周知fail指针int tot =0;// 节点数量voidinsertWord(string s){// 字典树操作,插入字符串int root =0;for(int i =0; i < s.size(); i ++){int next = s[i]-'a';if(!trie[root][next])
trie[root][next]=++tot;
root = trie[root][next];}
wordcnt[root]++;}voidbuildFail(){// 构建Fail数组
queue<int> que;
fail[0]=0;for(int i =0; i <26; i ++){int id = trie[0][i];if(id){
fail[id]=0;
que.push(id);}}while(!que.empty()){int now = que.front();que.pop();for(int i =0; i <26; i ++){int id = trie[now][i];if(id){
fail[id]= trie[fail[now]][i];
que.push(id);}else{
trie[now][i]= trie[fail[now]][i];}}}}intquery(string s){int mark[N];int now =0,res =0;for(int i =0;i < s.size(); i ++){
now = trie[now][s[i]-'a'];for(int j = now;j && wordcnt[j]!=-1; j = fail[j]){
res += wordcnt[j];
wordcnt[j]=-1;}}return res;}