算是ac自动机的入门题了吧。就是给了最多170个长为最多70的模板串,然后给出一个文本串,让按输入顺序输出所有的文本串匹配点最多的那些串。
因为模板串多个且长度较小,而文本串较长1e6,所
#include <queue>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define rep(i,n) for(int (i)=0;(i)<(n);i++)
#define Rep(i,n) for(int (i)=1;(i)<=(n);i++)
#define rep1(i,x,y) for(int (i)=x;(i)<=y;i++)
const int sigmasize = 26;
const int N = 71*151;
struct Aho_Corasick{
int ch[N][sigmasize];
int val[N],last[N],f[N],cou[N];
int cnt;
map<string,int> ms;
int idx(char c){return c-'a';}
void clear(){
cnt = 1;
memset(val,0,sizeof(val));
memset(ch[0],0,sizeof(ch[0]));
memset(cou,0,sizeof(cou));
ms.clear();
}
void insert(char* s,int v){
int n=strlen(s),u=0;
rep(i,n){
int c=idx(s[i]);
if(!ch[u][c]){
ch[u][c] = cnt;
memset(ch[cnt],0,sizeof(ch[cnt]));
cnt++;
}
u = ch[u][c];
}
val[u] = v;
ms[string(s)]=v;
}
void print(int i,int u){
if(u){
// printf("%d is found st position %d\n",val[u],i);
cou[val[u]]++;
print(i,last[u]);
}
}
void find(char* T){
int n=strlen(T),j=0;
rep(i,n){
int c=idx(T[i]);
j = ch[j][c];
if(val[j]) print(i,j);
else if(last[j]) print(i,last[j]);
}
}
void init(){
queue<int> Q;
last[0]=f[0]=0;
rep(i,sigmasize){
if(ch[0][i]) {
f[ch[0][i]]=last[i]=0;
Q.push(ch[0][i]);
}
}
while(!Q.empty()){
int r=Q.front(); Q.pop();
rep(i,sigmasize){
int u=ch[r][i];
if(!u){ch[r][i]=ch[f[r]][i]; continue;}
f[u]=ch[f[r]][i];
last[u] = val[f[u]] ? f[u]:last[f[u]];
Q.push(u);
}
}
}
};
int n,Q;
char str[180][100],src[1010101];
int main()
{
Aho_Corasick ac;
while(scanf("%d",&n)==1 && n){
ac.clear();
Rep(i,n){
scanf("%s",str[i]);
ac.insert(str[i],i);
}
ac.init();
scanf("%s",src);
ac.find(src);
int best = 0;
Rep(i,n) if(ac.cou[i]>best) {
best=ac.cou[i];
}
printf("%d\n",best);
Rep(i,n){
if(ac.cou[ac.ms[string(str[i])]] == best)
printf("%s\n",str[i]);
}
}
return 0;
}
以用ac自动机正合适,注意输出时重复的模板会覆盖前面的模板,要加一个ma<string,int>标记每个模板串最后出现的位置
即可。