病毒侵襲 HDU - 2896 AC自動機
阿新 • • 發佈:2018-11-19
題解
使用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;
}