P2444 [POI2000]病毒
作者:互联网
链接
题解
这题问我们能否构造一个无限长的串使得所有模式串均无法匹配,也就是说这个长串会在AC自动机上绕来绕去,不经过任何一个模式串的结尾。所以在trie图中有两类结点不能经过:表示单词结尾的结点和fail指针指向单词结尾的结点。如果剩下的trie边和转移边能形成环,才能构造出题目要求的串。
然后就变成了一个图论问题,用DFS找环。洛谷的数据很水,错误复杂度的DFS也能过。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 9;
struct tnode
{
int ch[2];
int cnt, fail;
};
tnode trie[maxn];
int tot, n;
bool flag[maxn], vis[maxn], used[maxn];
void ins(string &s)
{
int len = s.length(), now = 0;
for (int i = 0; i < len; ++i)
{
int c = s[i] - '0';
if (!trie[now].ch[c])
trie[now].ch[c] = ++tot;
now = trie[now].ch[c];
}
flag[now] = 1;
}
void build()
{
queue<int> q;
if (trie[0].ch[0])
q.push(trie[0].ch[0]);
if (trie[0].ch[1])
q.push(trie[0].ch[1]);
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = 0; i < 2; ++i)
{
int &now = trie[u].ch[i];
if (now)
{
trie[now].fail = trie[trie[u].fail].ch[i];
flag[now] |= flag[trie[now].fail];
q.push(now);
}
else
{
now = trie[trie[u].fail].ch[i];
}
}
}
}
bool dfs(int now)
{
vis[now] = 1;
for (int i = 0; i < 2; ++i)
{
int &to = trie[now].ch[i];
if (vis[to])
return 1;
if (flag[to] || used[to])
continue;
used[to] = 1;
if (dfs(to))
return 1;
}
vis[now] = 0;
return 0;
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n;
string s;
for (int i = 1; i <= n; ++i)
{
cin >> s;
ins(s);
}
build();
cout << (dfs(0) ? "TAK" : "NIE") << endl;
return 0;
}
标签:ch,trie,POI2000,int,flag,P2444,fail,now,病毒 来源: https://blog.csdn.net/Pastafarian/article/details/114739571