题意:给出一些模板串,再给出一些文本串,在这些文本串中找模式串
思路:题目中说每个病毒有唯一编号,不同编号的病毒不会相同,意味着不会有相同的模板串。貌似测试数据中也没有设置同一个网站里面有几个相同病毒的情况。每个网站最多三个病毒,也就是说找到了3个病毒就结束就醒了。ascii码可见字符有127个?
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxnode=100005;
const int sigma_size=130;
int f[maxnode];
int last[maxnode];
int virus[5];
int ans;
int idx(char c){return (int)c;}
struct Trie
{
int ch[maxnode][sigma_size];
int val[maxnode];
int sz;
int flag[maxnode];
Trie(){sz=1;memset(ch[0],0,sizeof(ch[0]));}
void init()
{
sz=1;
memset(ch[0],0,sizeof(ch[0]));
ans=0;
memset(f,0,sizeof(f));
memset(last,0,sizeof(last));
memset(flag,0,sizeof(flag));
}
void insert(char *s,int v)
{
int u=0;
int n=strlen(s);
for(int i=0;i<n;++i)
{
int c=idx(s[i]);
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
val[sz]=0;
ch[u][c]=sz++;
}
u=ch[u][c];
}
val[u]=v;
}
void find(char *T){
int n=strlen(T);
int j=0;
for(int i=0;i<n;++i)
{
int c=idx(T[i]);
while(j&& !ch[j][c])j=f[j];
j=ch[j][c];
if(val[j])print(j);
else if(last[j])print(last[j]);
if(ans>=3)return;
}
}
void print(int j){
if(j)
{
if(!flag[j])//不用这个判断也能过
{
virus[ans++]=val[j];flag[j]=1;
}
if(ans>=3)return;
print (last[j]);
}
}
void getFail()
{
queue<int> q;
f[0]=0;
for(int c=0;c<sigma_size;++c)
{
int u=ch[0][c];
if(u){f[u]=0;q.push(u);last[u]=0;}
}
while(!q.empty())
{
int r=q.front();q.pop();
for(int c=0;c<sigma_size;++c)
{
int u=ch[r][c];
if(!u)continue;
q.push(u);
int v=f[r];
while(v&&!ch[v][c])v=f[v];
f[u]=ch[v][c];
last[u]=val[f[u]]?f[u]:last[f[u]];
}
}
}
};
Trie tr;
int main()
{
//freopen("data.txt","r",stdin);
int n;
scanf("%d",&n);
tr.init();
for(int i=0;i<n;++i)
{
char s[205];
scanf("%s",s);
tr.insert(s,i+1);
}
tr.getFail();
scanf("%d",&n);
int tot=0;
for(int i=0;i<n;++i)
{
memset(tr.flag,0,sizeof(tr.flag));
ans=0;
char s[10005];
scanf("%s",s);
tr.find(s);
if(ans!=0)
{
sort(virus,virus+ans);
printf("web %d:",i+1);
for(int j=0;j<ans;++j)
{
printf(" %d",virus[j]);
}
printf("\n");
tot++;
}
}
printf("total: %d\n",tot);
return 0;
}