差不多也是裸题,将病毒特征码插入到字典树后对每个网站源码query一遍即可。当然要记得去重。
#include <bits/stdc++.h>
#define fi first
#define se second
#define FIN freopen("in.txt","r",stdin)
#define FIO freopen("out.txt","w",stdout)
#define INF 0x3f3f3f3f
#define per(i,a,n) for(int i = a;i < n;i++)
#define rep(i,a,n) for(int i = n;i > a;i--)
#define pern(i,a,n) for(int i = a;i <= n;i++)
#define repn(i,a,n) for(int i = n;i >= a;i--)
#define fastio std::ios::sync_with_stdio(false)
#define all(a) a.begin(), a.end()
#define ll long long
#define pb push_back
#define endl "\n"
#define mp make_pair
#define pii pair<int,int>
#define sc(n) scanf("%d", &n)
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
template<typename T> inline void _max(T &a,const T b){
if(a<b) a = b;}
template<typename T> inline void _min(T &a,const T b){
if(a>b) a = b;}
using namespace std;
inline ll read(){
ll a=0;int f=0;char p=getchar();
while(!isdigit(p)){
f|=p=='-';p=getchar();}
while(isdigit(p)){
a=(a<<3)+(a<<1)+(p^48);p=getchar();}
return f?-a:a;
}
const int maxn = 10000*50;
const int maxnode = 135;
int ch[maxn][maxnode];//字典树
int cnt[maxn];//单词出现次数
int val[maxn];
int sz;
void init()
{
sz = 0;
memset(ch[0],0,sizeof(ch[0]));
val[0] = 0;
cnt[0] = 0;
}
void insert(char str[],int len,int id)//插入字符串
{
int u = 0;
per(i,0,len)
{
int v = str[i];
if(!ch[u][v])
{
sz++;
memset(ch[sz],0,sizeof(ch[sz]));
//val[sz] = 0;
cnt[sz] = 0;
ch[u][v] = sz;
}
u = ch[u][v];
}
cnt[u]++;
val[u] = id;
//cout << u << ' ';
//在这里我们可以建立一个int-string的映射,以通过节点序号得知这个点是哪个单词的结尾
}
int fail[maxn];
void getfail()
{
//所有模式串已插入完成
queue<int> q;
fail[0] = 0;
per(i,0,maxnode)
{
if(ch[0][i])
{
fail[ch[0][i]] = 0;
q.push(ch[0][i]);
}
}
while(!q.empty())
{
int now = q.front();
q.pop();
per(i,0,maxnode)
{
if(ch[now][i])
{
fail[ch[now][i]] = ch[fail[now]][i];
q.push(ch[now][i]);
}
else
ch[now][i] = ch[fail[now]][i];
}
}
}
void query(char str[],int len,vector<int>& ans)
{
int now = 0;
per(i,0,len)
{
now = ch[now][str[i]];
int j = now;
while(j && cnt[j]!=-1)
{
//cout << j << ' ';
if(val[j])
ans.push_back(val[j]);
//cnt[j] = -1;//防止重复计算。这里可以将j映射到string,以具体统计每个模式串出现的次数。j即节点序号,模式串与其是一一对应的关系
j = fail[j];
}
}
return;// ans;
}
char s[1000000+10];
char virus[500+10][200+10];
int main()
{
#ifndef ONLINE_JUDGE
int startTime = clock();
FIN;
#endif
//fastio;
//忘记初始化是小狗
//freopen("out.txt","w",stdout);
//ios::sync_with_stdio(false);
int n,m;
vector<int> ans;
sc(n);
init();
per(i,0,n)
{
scanf("%s",virus[i]);
// printf("%s\n",s);
insert(virus[i],strlen(virus[i]),i+1);
}
getfail();
sc(m);
int c = 0;
per(i,0,m)
{
scanf("%s",s);
ans.clear();
query(s,strlen(s),ans);
sort(ans.begin(),ans.end());
//unique(ans.begin(),ans.end());
if(ans.size()>0){
c++;
printf("web %d:",i+1);
printf(" %d",ans[0]);
per(j,1,ans.size())
{
if(ans[j]!=ans[j-1])
printf(" %d",ans[j]);
}
printf("\n");
}
}
printf("total: %d\n",c);
#ifndef ONLINE_JUDGE
printf("\nTime = %dms\n", clock() - startTime);
#endif
return 0;
}