P2444 [POI2000] 病毒
[P2444 POI2000] 病毒 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
问题等价于在字典图中找一个环,这个环要满足环上节点不是所有所给字符串最后一个字符结尾的点。
找环算法:
void dfs(int u) {
in[u] = 1; // u在当前dfs路径中
for(auto y: g[u]) {
if(in[y]) {
// 与dfs路径中点重合,成环
fg = 1;
}
// 如果之前已经访问过y点,表示经过y点不会有环
if(vis[y]) continue;
vis[y] = 1;
dfs(y);
}
in[u] = 0;
}
本题找环,还需要保证,y点不是所给字符串中最后一个字符结尾的点。
代码:
#include <iostream>
#include <vector>
#include <string>
#include <cstring>
#include <set>
#include <map>
#include <queue>
#include <ctime>
#include <random>
#include <sstream>
#include <numeric>
#include <stdio.h>
#include <functional>
#include <bitset>
#include <algorithm>
using namespace std;
// #define Multiple_groups_of_examples
// #define int_to_long_long
#define IOS std::cout.tie(0);std::cin.tie(0)->sync_with_stdio(false); // 开IOS,需要保证只使用Cpp io流 *
#define dbgnb(a) std::cout << #a << " = " << a << '\n';
#define dbgtt cout<<" !!!test!!! "<<'\n';
#define rep(i,x,n) for(int i = x; i <= n; i++)
#define all(x) (x).begin(),(x).end()
#define pb push_back
#define vf first
#define vs second
typedef long long LL;
#ifdef int_to_long_long
#define int long long
#endif
typedef pair<int,int> PII;
const int INF = 0x3f3f3f3f;
const int N = 2e5 + 21;
namespace golitter {
namespace ACAM {
// https://www.luogu.com.cn/problem/P5357
// https://zhuanlan.zhihu.com/p/546999184
struct acam {
static const int M = 300005;
struct node {
int fail;
int ch[28] = {0};
}tr[M];
int cnt = 0;
map<int,int> ref;
vector<int> g[M];
int ans[M];
bitset<M> in, vis, isend;
void insert(string &s, int id) {
int u = 0;
for(auto c: s) {
int last = c == '_' ? 26 : c - 'a';
if(!tr[u].ch[last]) {
tr[u].ch[last] = ++cnt;
}
u = tr[u].ch[last];
}
isend[u] = 1;
ref[id] = u;
}
void build() {
queue<int> que;
for(int i = 0; i < 27; ++i) {
if(tr[0].ch[i]) que.push(tr[0].ch[i]);
}
while(que.size()) {
int u = que.front(); que.pop();
for(int i = 0; i < 27; ++i) {
if(tr[u].ch[i]) {
tr[tr[u].ch[i]].fail = tr[tr[u].fail].ch[i];
que.push(tr[u].ch[i]);
if(isend[tr[tr[u].ch[i]].fail]) isend[tr[u].ch[i]] = 1;
} else tr[u].ch[i] = tr[tr[u].fail].ch[i];
}
}
for(int i = 1; i <= cnt; ++i) g[tr[i].fail].push_back(i);
}
void query(string &S) {
int u = 0;
for(auto c: S) {
int last = c == '_' ? 26 : c - 'a';
u = tr[u].ch[last];
ans[u]++;
}
}
bool fg = 0;
bool check() {
dfs(0);
return fg;
}
void dfs(int u) {
in[u] = 1;
for(int i = 0; i <= 1; ++i) {
if(in[tr[u].ch[i]]) {
fg = 1;
return ;
}
if(vis[tr[u].ch[i]] || isend[tr[u].ch[i]]) continue;
vis[tr[u].ch[i]] = 1;
dfs(tr[u].ch[i]);
}
in[u] = 0;
}
void clear() {
for(int i = 0; i < M; ++i) {
tr[i] = {};
g[i].clear();
ans[i] = 0;
}
ref.clear();
cnt = 0;
}
}trie;
}}
using golitter::ACAM::trie;
void inpfile();
void solve() {
int n; cin>>n;
for(int i = 0; i< n; ++i) {
string s; cin>>s;
for(auto&t: s) {
if(t == '1') t = 'b';
else t = 'a';
}
trie.insert(s, i);
}
trie.build();
puts(trie.check() ? "TAK" : "NIE");
}
#ifdef int_to_long_long
signed main()
#else
int main()
#endif
{
#ifdef Multiple_groups_of_examples
int T; cin>>T;
while(T--)
#endif
solve();
return 0;
}
void inpfile() {
#define mytest
#ifdef mytest
freopen("ANSWER.txt", "w",stdout);
#endif
}