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
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

golemon.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值