病毒侵袭 HDU - 2896 AC自动机

题解

使用AC自动机求解 插入病毒串时记录病毒串id 题目保证不同的串有不同的id直接记录即可 使用vis数组记录主串编号 同编号标记的不在处理 注意字符集为所有可见字符
题目内存卡的比较紧 不要使用memset清空数组否则会MLE 原因是开启O2优化时会只消耗使用过的内存

AC代码

#include <stdio.h>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int INF = 0x3f3f3f3f;
const int MAXN = 1e5 + 10; //卡内存
const int MAXC = 128;
int nxt[MAXN][MAXC], sed[MAXN], vis[MAXN], fal[MAXN], idx; //nxt
char s[MAXN];
vector<int> ans;

inline int ID(char c) //
{
	return c;
}
void Insert(char *s, int n, int id) //
{
	int x = 0;
	for (int i = 0; i < n; i++)
	{
		int c = ID(s[i]);
		if (!nxt[x][c])
			nxt[x][c] = ++idx;
		x = nxt[x][c];
	}
	sed[x] = id;
}
void Build()
{
	queue<int> q;
	for (int i = 0; i < MAXC; i++)
		if (nxt[0][i])
			q.push(nxt[0][i]);
	while (!q.empty())
	{
		int f = q.front();
		q.pop();
		for (int i = 0; i < MAXC; i++)
			if (nxt[f][i])
				fal[nxt[f][i]] = nxt[fal[f]][i], q.push(nxt[f][i]);
			else
				nxt[f][i] = nxt[fal[f]][i];
	}
}
void Match(char *s, int n, int id) //
{
	ans.clear();
	int x = 0;
	for (int i = 0; i < n; i++)
	{
		int c = ID(s[i]);
		x = nxt[x][c];
		for (int p = x; p && vis[p] != id; p = fal[p])
		{
			if (sed[p])
				ans.push_back(sed[p]);
			vis[p] = id;
		}
	}
	sort(ans.begin(), ans.end());
}
int main()
{
#ifdef LOCAL
	freopen("C:/input.txt", "r", stdin);
#endif
	int N, M;
	cin >> N;
	for (int i = 1; i <= N; i++)
		scanf("%s", s), Insert(s, strlen(s), i);
	Build();
	cin >> M;
	int tot = 0;
	for (int i = 1; i <= M; i++)
	{
		scanf("%s", s);
		Match(s, strlen(s), i);
		if (ans.size())
		{
			printf("web %d:", i);
			for (int j = 0; j < ans.size(); j++)
				printf(" %d", ans[j]);
			putchar('\n');
			tot++;
		}
	}
	cout << "total: " << tot << endl;

	return 0;
}

猜你喜欢

转载自blog.csdn.net/CaprYang/article/details/83247530
今日推荐