题目传送门
题意解析:似乎题目是中文的,所以就大概说一下,给你n个模式串,和m个匹配串,让你找出分别是哪几个模式串出现了,题目中保证了匹配串中最多出现3个模式串,并且最后让你输出可以匹配的个数。
AC自动机的裸题,在危险节点上记录编号就好了。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#define rep(i,a,n) for (int i=a;i<=n;i++)
#define per(i,a,n) for (int i=a;i>=n;i--)
#define Clear(a,x) memset(a,x,sizeof(a))
#define ll long long
#define INF 2000000000
#define eps 1e-8
using namespace std;
int read(){
int x=0,f=1;
char ch=getchar();
while (ch<'0'||ch>'9') f=ch=='-'?-1:f,ch=getchar();
while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
return x*f;
}
const int maxnode=100005,maxsize=128;
char s[10005];
int n,m,ans;
struct AC{
int ch[maxnode][maxsize],val[maxnode],f[maxnode];
int cnt;
inline void init(){
cnt=0;
Clear(ch[0],0);
val[0]=f[0]=0;
}
inline void insert(char *s,int v){
int len=strlen(s),u=0;
rep(i,0,len-1){
int id=s[i];
if (!ch[u][id]){
ch[u][id]=++cnt;
Clear(ch[cnt],0);
val[cnt]=0;
}
u=ch[u][id];
}
val[u]=v;
}
inline void getfail(){
queue<int> q;
f[0]=0;
rep(i,0,maxsize-1){
int u=ch[0][i];
if (u){
f[u]=0;
q.push(u);
}
}
while (!q.empty()){
int r=q.front();
q.pop();
rep(i,0,maxsize-1){
int u=ch[r][i];
if (!u) ch[r][i]=ch[f[r]][i];
else{
f[u]=ch[f[r]][i];
q.push(u);
}
}
}
}
int a[505];
inline void find(char *s,int v){
int len=strlen(s),u=0;
int tot=0;
bool flag=0;
rep(i,0,len-1){
int id=s[i];
u=ch[u][id];
int tmp=u;
while (tmp!=0){
if (val[tmp]){
a[++tot]=val[tmp];
flag=1;
}
tmp=f[tmp];
}
}
if (!flag) return;
ans++;
printf("web %d: ",v);
sort(a+1,a+tot+1);
rep(i,1,tot-1) printf("%d ",a[i]);
printf("%d\n",a[tot]);
}
}ac;
int main(){
while (~scanf("%d",&n)){
ac.init();
rep(i,1,n){
scanf("%s",s);
ac.insert(s,i);
}
ac.getfail();
ans=0;
m=read();
rep(i,1,m){
scanf("%s",s);
ac.find(s,i);
}
printf("total: %d\n",ans);
}
return 0;
}
总感觉用结构体比较漂亮。