ybtoj+luoguP2444+E. 【例题5】病毒代码(POI2000)

思路:先构建出一个ac自动机,将他优化成tire图,标记含有病毒代码的点P的flag=1,bfs这个图,从根节点开始,标记过的点不走,如果最后形成自环,则可以安全代码,否则bfs结束,没有安全代码;

涉及算法(bfs+ac自动机+tire图优化);

code:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 2e3 + 10, M = 3e4 + 10;
int ne[M] = { 0 }, son[M][2], idx = 1, vis[M], flag[M], que[M];
bool st[M] = { 0 };
char s[N][M];
inline void insert(char str[]) {
    int p = 1, len = strlen(str + 1);
    for (int i = 1; i <= len; i++) {
        int u = str[i] - '0';
        if (!son[p][u])
            son[p][u] = ++idx;
        p = son[p][u];
    }
    st[p] = 1;
}
inline void build() {
    for (int i = 0; i < 2; i++) son[0][i] = 1;
    ne[1] = 0, que[1] = 1;
    for (int q1 = 1, q2 = 1; q1 <= q2; q1++) {
        int u = que[q1];
        for (int i = 0; i < 2; i++) {
            int v = ne[u], w = son[u][i];
            while (!son[v][i]) v = ne[v];
            v = son[v][i];
            if (w) {
                ne[w] = v, st[w] |= st[v];
                que[++q2] = w;
            } else {
                son[u][i] = v;
            }
        }
    }
}
inline void dfs(int u) {
    vis[u] = flag[u] = 1;
    for (int i = 0, v; i < 2; i++) {
        v = son[u][i];
        if (vis[v]) {
            cout << "TAK" << endl;
            exit(0);
        } else if (!st[v] && !flag[v])
            dfs(v);
    }
    vis[u] = 0;
}
int main() {
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++) {
        scanf("%s", s[i] + 1);
        insert(s[i]);
    }
    build();

    dfs(1);
    cout << "NIE" << endl;
    return 0;
}

如有不解,可以私信

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值