病毒侵袭(HDU-2896)
AC自动机模板题
题目详情:
啊是中文的,那就不解释了
就是关于多个串匹配一个文本串,不过这题的坑真不少!!!
坑:以上字符串中字符都是ASCII码可见字符(不包括回车)。
要用 vis数组来判断,不能直接 word[i]==1
输入中的空格不用理会 估计是数据太弱
要记得排序
这题算是一道模板吧,时间有点仓促,下次好好整理整理
#include <bits/stdc++.h>
#define maxn 110000
using namespace std;
int trie[maxn][130];
int cnt,n,m,ans,total,d;
int word[maxn],fail[maxn];
int s1[maxn];
int tag[maxn],number;
int vis[maxn];
void insert(string s){
int root = 0;
for(int i=0;i<s.size();i++){
int p = s[i];
if(!trie[root][p]) trie[root][p] = ++cnt;
root = trie[root][p];
}
word[root]++;
tag[root] = ++number;
}
void getfail(){
queue<int> q;
for(int i=0;i<130;i++){
if(trie[0][i]){
q.push(trie[0][i]);
fail[trie[0][i]] = 0;
}
}
while(!q.empty()){
int tmp = q.front();
q.pop();
for(int i=0;i<130;i++){
int m = trie[tmp][i];
if(m){
fail[m] = trie[fail[tmp]][i];
q.push(m);
}
else
trie[tmp][i] = trie[fail[tmp]][i];
}
}
}
void query(string s){
int root = 0;
for(int i=0;i<s.size();i++){
root = trie[root][s[i]];
for(int j=root; j&&vis[j]!=1 ; j=fail[j]){
ans += word[j];
if(word[j]>0) s1[d++] = tag[j];
vis[j] = 1;
}
}
}
int main(){
string s;
std::ios::sync_with_stdio(false);
cin>>n;
for(int i=0;i<n;i++){
cin>>s;
insert(s);
}
getfail();
cin>>m;
for(int i=1;i<=m;i++){
memset(s1,0,sizeof(s1));
memset(vis,0,sizeof(vis));
ans = 0;
d = 0;
cin>>s;
query(s);
if(ans){
total++;
printf("web %d:",i);
sort(s1,s1+d); //sort
for(int r=0;r<d;r++){
printf(" %d",s1[r]);
}
printf("\n");
}
}
printf("total: %d\n",total);
return 0;
}