大致题意: 一道模板题,给你\(N\)个模式串和一个文本串,要你求出在文本串中出现次数最多的若干个模式串并输出它们。
\(AC\)自动机
都说了是的模板题,做法肯定是\(AC\)自动机。
题解
我们可以考虑在将每个模式串插入\(Trie\)后,记录下每个模式串最后到达的节点。
然后,在\(AC\)自动机时,将每一个经过的节点的访问次数加1。
最后统计答案时,只要求出最后到达的节点被访问次数最大的若干个模式串并输出即可,应该可以算是一道比较裸的模板题。
代码
#include#define max(x,y) ((x)>(y)?(x):(y))#define min(x,y) ((x)<(y)?(x):(y))#define LL long long#define swap(x,y) (x^=y,y^=x,x^=y)#define pc(ch) (pp_<100000?pp[pp_++]=(ch):(fwrite(pp,1,100000,stdout),pp[(pp_=0)++]=(ch)))#define N 150#define SUM 1000000int pp_=0;char pp[100000];using namespace std;int n,tot=1,rt=1,ans=0,f[N+5];struct Trie{ int Son[26],Vis,Next;}node[SUM+5];string s[N+5],st;queue q;vector res;inline void write(int x){ if(x>9) write(x/10); pc(x%10+'0');}inline void ps(string x){ register int i,len=x.length(); for(i=0;i >s[i],Insert(i,s[i]); for(cin>>st,GetNext(),AC_Automation(),i=1;i<=n;++i) { if(node[f[i]].Vis>ans) ans=node[f[i]].Vis,res.clear(),res.push_back(i);//比较当前模式串所对应的Trie上的节点被访问的次数与ans的大小,如果当前模式串出现的次数大于ans,就更新ans else if(node[f[i]].Vis==ans) res.push_back(i);//否则,如果当前模式串出现的次数等于ans,就将当前模式串加入最后要输出的数组中 } for(write(ans),pc('\n'),i=0;i