您的位置:首页 > 其它

[luoguP2444] [POI2000]病毒(AC自动机 + dfs)

2017-05-09 15:02 197 查看

传送门

 

先把所有串建一个AC自动机,

如果要找一个不包含任意一个串的串,

说明这个串一直在AC自动机上匹配但匹配不到,

也就是说,匹配时除去val值为1的点,除去fail指针指向val值为1的点,是否有环,dfs即可。

因为val值为1说明匹配上,fail指针指向的点x,根到x所形成的字符串是当前串的后缀,

所以也得除去fail指针指向val值为1的点的点。

 

——代码

#include <queue>
#include <cstdio>
#include <cstring>

using namespace std;

const int MAXN = 30001;
int n, cnt;
int ch[MAXN << 2][2], fail[MAXN << 2];
char s[MAXN];
bool vis[MAXN << 2], ins[MAXN << 2], val[MAXN << 2];
queue <int> q;

inline void insert()
{
int i, x, len = strlen(s), now = 0;
for(i = 0; i < len; i++)
{
x = s[i] - '0';
if(!ch[now][x]) ch[now][x] = ++cnt;
now = ch[now][x];
}
val[now] = 1;
}

inline void make_fail()
{
int i, x, now;
for(i = 0; i <= 1; i++) if(ch[0][i]) q.push(ch[0][i]);
while(!q.empty())
{
now = q.front(), q.pop();
for(i = 0; i <= 1; i++)
{
if(!ch[now][i])
{
ch[now][i] = ch[fail[now]][i];
continue;
}
fail[ch[now][i]] = ch[fail[now]][i];
q.push(ch[now][i]);
val[ch[now][i]] |= val[fail[ch[now][i]]];
}
}
}

inline bool dfs(int u)
{
int i, v;
ins[u] = 1;
for(i = 0; i <= 1; i++)
{
v = ch[u][i];
if(ins[v]) return 1;
if(val[v] || vis[v]) continue;
vis[v] = 1;
if(dfs(v)) return 1;
}
ins[u] = 0;
return 0;
}

int main()
{
int i, j;
scanf("%d", &n);
for(i = 1; i <= n; i++)
{
scanf("%s", s);
insert();
}
make_fail();
if(dfs(0)) puts("TAK");
else puts("NIE");
return 0;
}
View Code

 

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