您的位置:首页 > 其它

【练习05】 AC自动机 1001 病毒侵袭

2013-07-22 13:01 651 查看
算法思路:AC自动机。

要点:

1.val存储病毒的编号;

2.find函数中当找到一个模板后,应该顺着失配边往回走,由last数组递归判断是否还有其他的子模板能够匹配,所有找到的模板的val值保存到数组save中。

3.对save数组进行sort排序,注意输出格式,依次打印病毒编号。

4.题中要求是“可见字符”,在不超内存的情况下,sigma_size最好开到127。

//模板开始
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <sstream>
#include <fstream>
#include <map>
#include <set>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <string.h>
#include <queue>
#define SZ(x) (int(x.size()))
using namespace std;

int toInt(string s){
istringstream sin(s);
int t;
sin>>t;
return t;
}
template<class T> string toString(T x){
ostringstream sout;
sout<<x;
return sout.str();
}
typedef long long int64;
int64 toInt64(string s){
istringstream sin(s);
int64 t;
sin>>t;
return t;
}
template<class T> T gcd(T a, T b){
if(a<0)
return gcd(-a, b);
if(b<0)
return gcd(a, -b);
return (b == 0)? a : gcd(b, a % b);
}
//模板结束(通用部分)

#define ifs cin

#define maxnode 100005
#define sigma_size 127

int save[maxnode];
int cnt;

struct Trie
{
int ch[maxnode][sigma_size];
int val[maxnode];
int sz;
int f[maxnode];
int last[maxnode];
Trie()
{
sz = 1;
memset(ch[0], 0, sizeof(ch[0]));
}
int idx(char c)
{
return (int)c;
}

void insert(char* s, int v)
{
int u = 0, 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;
}

//int search(char* s, int n)
//{
//	int u = 0;
//	int flag = 1;
//	for(int i = 0; i < n; i++)
//	{
//		int c = idx(s[i]);
//		if(ch[u][c] == 0)
//		{
//			flag = 0;
//			break;
//		}
//		u = ch[u][c];
//	}
//	if(flag && val[u])
//	{
//		return 1;
//	}
//	else
//	{
//		return 0;
//	}
//}

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]];
}
}
}
}

void save_all(int j)
{
if(j)
{
save_all(last[j]);
save[cnt++] = val[j];
}
}

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])
{
save_all(j);
}
else
{
if(last[j])
{
save_all(last[j]);
}
}
}
}
};

Trie t;
char a[505][205];
char b[10005];
int jishu;

//【练习05】 AC自动机 1001 病毒侵袭

int main()
{
//ifstream ifs("shuju.txt", ios::in);
int n;
while(ifs>>n)
{
for(int i = 1; i <= n; i++)
{
//ifs>>a[i];
scanf("%s", &a[i]);
t.insert(a[i], i);
}
t.getFail();

ifs>>n;
jishu = 0;
for(int i = 1; i <= n; i++)
{
//ifs>>b;
scanf("%s", &b);
cnt = 0;
memset(save, 0, sizeof(save));
t.find(b);
if(!save[0])
{
continue;
}
else
{
jishu++;
}
sort(save, save + cnt);
cout<<"web "<<i<<":";
for(int j = 0; j < cnt; j++)
{
cout<<" "<<save[j];
}
cout<<endl;
}
cout<<"total: "<<jishu<<endl;
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: