1. 程式人生 > >病毒侵襲 HDU - 2896 AC自動機

病毒侵襲 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; }