貌似字典树也能过,原理不多赘述了,主要就是字典树+kmp
设匹配串长度为n,模式串共m个,第i个记为si。
时间复杂度为O(n+∑mi=1length(si))。
ac自动机大致就是用字典树存下每个分串,再处理出fail数组,最后根据母串和fail数组进行逐一匹配
在对fail数组进行处理的时候,fail指向的是后缀相同且最长那一个节点
(wa点:trie应该开全局变量,query时,以为是从root开始0到26进行向下匹配)
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-7; const int N=500000+10,maxn=60000+10,inf=0x3f3f3f; struct Trie{ int Next[N][26],fail[N],cnt[N]; int root,tot; int newnode() { for(int i=0;i<26;i++) Next[tot][i]=-1; cnt[tot]=0; return tot++; } void init() { tot=0; root=newnode(); } void insertstring(string s)//插入字符串,构成字典树 { int now=root; for(int i=0;i<s.size();i++) { if(Next[now][s[i]-'a']==-1) Next[now][s[i]-'a']=newnode(); now=Next[now][s[i]-'a']; } ++cnt[now];//每个字符串末尾++ } void build()//构建fail数组,和next数组 { queue<int>q; fail[root]=root; for(int i=0;i<26;i++) { if(Next[root][i]==-1)Next[root][i]=root; else { fail[Next[root][i]]=root; q.push(Next[root][i]); } } while(!q.empty()) { int now=q.front(); q.pop(); for(int i=0;i<26;i++) { if(Next[now][i]==-1)Next[now][i]=Next[fail[now]][i]; else { fail[Next[now][i]]=Next[fail[now]][i]; q.push(Next[now][i]); } } } } int query(string s) { int now=root,res=0; for(int i=0;i<s.size();i++) { // cout<<now<<" "; now=Next[now][s[i]-'a']; int temp=now; while(temp!=root) { // cout<<temp<<" "; res+=cnt[temp]; cnt[temp]=0; temp=fail[temp]; } // cout<<endl; } return res; } void debug() { for(int i=0;i<tot;i++) { cout<<i<<" "<<fail[i]<<" "<<cnt[i]<<" "; for(int j=0;j<26;j++) cout<<Next[i][j]<<" \n"[i==25]; cout<<endl; } } }; Trie acm; string s; int main() { ios::sync_with_stdio(false); cin.tie(0); int t,n; cin>>t; while(t--) { cin>>n; acm.init(); for(int i=1;i<=n;i++) { cin>>s; acm.insertstring(s); } acm.build(); // acm.debug(); cin>>s; cout<<acm.query(s)<<endl; } return 0; } /******************** 1 4 abce abd cd bce abcde ********************/