题目大意:
给定$n(nleq150)$个模式串$p_i(|p_i|le70)$和一个$t(|t|le10^6)$,求$t$中被匹配次数最多的$p_i$。
思路:
AC自动机。匹配时记录一下匹配次数即可。
1 #include<queue> 2 #include<cstdio> 3 #include<cctype> 4 #include<algorithm> 5 inline int getint() { 6 register char ch; 7 while(!isdigit(ch=getchar())); 8 register int x=ch^'0'; 9 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 10 return x; 11 } 12 const int N=150,L1=71,L2=1e6+1,S=26; 13 int cnt[N]; 14 char s[N][L1],t[L2]; 15 class AhoCorasick { 16 private: 17 std::queue<int> q; 18 int val[N*L1]={-1},ch[N*L1][S],fail[N*L1]; 19 int sz,new_node() { 20 fail[++sz]=0; 21 val[sz]=-1; 22 std::fill(&ch[sz][0],&ch[sz][S],0); 23 return sz; 24 } 25 int idx(const int &c) const { 26 return c-'a'; 27 } 28 public: 29 void reset() { 30 std::fill(&ch[0][0],&ch[0][S],sz=0); 31 } 32 void insert(const char s[],const int &id) { 33 int p=0; 34 for(register int i=0;s[i];i++) { 35 const int c=idx(s[i]); 36 p=ch[p][c]?:ch[p][c]=new_node(); 37 } 38 val[p]=id; 39 } 40 void get_fail() { 41 for(register int i=0;i<S;i++) { 42 if(ch[0][i]) q.push(ch[0][i]); 43 } 44 while(!q.empty()) { 45 const int &x=q.front(); 46 for(register int i=0;i<S;i++) { 47 int &y=ch[x][i]; 48 if(!y) { 49 y=ch[fail[x]][i]; 50 continue; 51 } 52 fail[y]=ch[fail[x]][i]; 53 q.push(y); 54 } 55 q.pop(); 56 } 57 } 58 void find(const char s[]) { 59 for(register int i=0,p=0;s[i];i++) { 60 for(register int j=p=ch[p][idx(s[i])];j;j=fail[j]) { 61 if(~val[j]) cnt[val[j]]++; 62 } 63 } 64 } 65 }; 66 AhoCorasick ac; 67 int main() { 68 for(int n;(n=getint());) { 69 ac.reset(); 70 for(register int i=0;i<n;i++) { 71 cnt[i]=0; 72 scanf("%s",s[i]); 73 ac.insert(s[i],i); 74 } 75 ac.get_fail(); 76 scanf("%s",t); 77 ac.find(t); 78 int ans=0; 79 for(register int i=0;i<n;i++) ans=std::max(ans,cnt[i]); 80 printf("%d ",ans); 81 for(register int i=0;i<n;i++) { 82 if(cnt[i]==ans) puts(s[i]); 83 } 84 } 85 return 0; 86 }