[POI 2000] 病毒

[题目链接]

[算法]

首先建出给定字符串集的AC自动机

存在无限长的代码当且仅当 ： AC自动机上存在一个环且环上没有危险节点

时间复杂度 ： O(N)

[代码]

```#include<bits/stdc++.h>
using namespace std;
#define MAXP 300010
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;

int n;
char s[MAXP];

struct AC_Automation
{
int sz , rt , timer;
int fail[MAXP];
bool danger[MAXP] , vis[MAXP] , ins[MAXP];
int child[MAXP][2];
inline void init()
{
timer = 0;
sz = 0;
rt = newnode();
}
inline void chkmin(int &x , int y)
{
x = min(x , y);
}
inline int newnode()
{
++sz;
child[sz][0] = child[sz][1] = -1;
fail[sz] = danger[sz] = 0;
return sz;
}
inline void insert(char *s)
{
int now = rt;
for (int i = 1; i <= strlen(s + 1); i++)
{
int nxt = s[i] - ‘0‘;
if (child[now][nxt] == -1) child[now][nxt] = newnode();
now = child[now][nxt];
}
danger[now] = 1;
}
inline void rebuild()
{
queue< int > q;
fail[rt] = rt;
for (int i = 0; i < 2; i++)
{
if (child[rt][i] == -1)
child[rt][i] = rt;
else
{
fail[child[rt][i]] = rt;
q.push(child[rt][i]);
}
}
while (!q.empty())
{
int cur = q.front();
q.pop();
for (int i = 0; i < 2; i++)
{
if (child[cur][i] == -1)
child[cur][i] = child[fail[cur]][i];
else
{
fail[child[cur][i]] = child[fail[cur]][i];
danger[child[cur][i]] |= danger[fail[child[cur][i]]];
q.push(child[cur][i]);
}
}
}
}
inline void solve(int now)
{
if (ins[now])
{
printf("TAK\n");
exit(0);
}
if (vis[now] || danger[now]) return;
vis[now] = ins[now] = 1;
if (child[now][0] != -1) solve(child[now][0]);
if (child[now][1] != -1) solve(child[now][1]);
ins[now] = 0;
}
} ACAM;

template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
template <typename T> inline void read(T &x)
{
T f = 1; x = 0;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -f;
for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - ‘0‘;
x *= f;
}

int main()
{

scanf("%d" , &n);
ACAM.init();
for (int i = 1; i <= n; i++)
{
scanf("%s" , s + 1);
ACAM.insert(s);
}
ACAM.rebuild();
ACAM.solve(1);
printf("NIE\n");

return 0;
}```

[POI 2000] 病毒

(0)
(0)