【Luogu】P2444 [POI2000] Virus——AC Automata

Topic link

Title description

The Binary Virus Review Committee recently discovered the following rule: some certain binary strings are virus codes. If there is no virus code in a certain piece of code, then we call this piece of code safe. Now that the committee has found all the virus code segments, let’s ask if there is an infinitely long safe binary code.

Example:

For example, if {011, 11, 00000} is a virus code segment, then a possible infinite security code is 010101... If {01, 11, 000000} is a virus code segment, then there is no infinite security code.

task:

Please write a program:

1. Read the virus code in the text file WIR.IN;

2. Determine whether there is an infinite security code;

3. Output the result to the file WIR.OUT.

Input format

The first line of the text file WIR.IN includes an integer n(n\le 2000) (n≤2000), which represents the number of virus code segments. Each of the following n lines contains a non-empty 01 string-it is a virus code segment. The total length of all virus code segments does not exceed 30,000.

Output format

Output a word in the first line of the text file WIR.OUT:

TAK-if there is such a code;

NIE-if it does not exist.

Sample input and output

enter

3
01
11
00000

Output

NO

analysis

Find a way to make the infinitely long string continuously mismatch on the tree, and then keep walking the fail pointer and finally enter a loop.

That is, dfs on the tree, ensuring that no end node of the string is passed so that a ring on the tree is found

AC code

#include <bits/stdc++.h>

using namespace std;

/*
 * AC 自动机:多个模式串去匹配一个串,求有多少个模式串与主串有匹配内容
 *
 * 使用操作:
 * 1、把每一个模式串插入到树中 insert
 * 2、build
 * 3、使用 query 询问有多少个模式串匹配
 */

const int CHAR_NUM = 2;//仅小写
const int MAXN = 2100;//模式串个数
const int MAXM = 30100;//模式串最长长度
const int NUM = MAXN * MAXM;//空间=个数*长度,稳

struct Trie {
    
    
    int c[NUM][CHAR_NUM], val[NUM], fail[NUM], cnt;

    void insert(char *s) {
    
    
        int len = strlen(s);
        int now = 0;
        for (int i = 0; i < len; i++) {
    
    
//            int v = s[i] - 'a';
            int v = s[i] - '0';
            if (!c[now][v])c[now][v] = ++cnt;
            now = c[now][v];
        }
        val[now]++;
    }

    void build() {
    
    
        queue<int> q;
        for (int i = 0; i < CHAR_NUM; i++)if (c[0][i])fail[c[0][i]] = 0, q.push(c[0][i]);
        while (!q.empty()) {
    
    
            int u = q.front();
            q.pop();
            for (int i = 0; i < CHAR_NUM; i++)
                if (c[u][i])fail[c[u][i]] = c[fail[u]][i], q.push(c[u][i]);
                else c[u][i] = c[fail[u]][i];
        }
    }

    int query(char *s) {
    
    
        int len = strlen(s);
        int now = 0, ans = 0;
        for (int i = 0; i < len; i++) {
    
    
//            now = c[now][s[i] - 'a'];
            now = c[now][s[i] - '0'];
            for (int t = now; t && ~val[t]; t = fail[t])ans += val[t], val[t] = -1;
        }
        return ans;
    }
} AC;

char s[30100];
bool vis[NUM];

bool dfs(int cur) {
    
    
    for (int i = 0; i < CHAR_NUM; ++i) {
    
    
        int x = AC.c[cur][i];
        if (!AC.val[x]) {
    
    
            bool flag = false;
            int t = x;
            while (t) {
    
    
                if (AC.val[t]) {
    
    
                    flag = true;
                    break;
                }
                t = AC.fail[t];
            }
            if (flag)
                continue;
            if (vis[x])
                return true;
            vis[x] = true;
            if (dfs(x)) {
    
    
                return true;
            }
            vis[x] = false;
        }
    }
    return false;
}

void solve() {
    
    
    int n;
    cin >> n;
    for (int i = 0; i < n; ++i) {
    
    
        cin >> s;
        AC.insert(s);
    }
    AC.build();
    vis[0] = true;
    bool flag = dfs(0);
    if (flag) {
    
    
        cout << "TAK" << endl;
    } else {
    
    
        cout << "NIE" << endl;
    }
}

int main() {
    
    
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
#ifdef ACM_LOCAL
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    long long test_index_for_debug = 1;
    char acm_local_for_debug;
    while (cin >> acm_local_for_debug) {
    
    
        cin.putback(acm_local_for_debug);
        if (test_index_for_debug > 20) {
    
    
            throw runtime_error("Check the stdin!!!");
        }
        auto start_clock_for_debug = clock();
        solve();
        auto end_clock_for_debug = clock();
        cout << "Test " << test_index_for_debug << " successful" << endl;
        cerr << "Test " << test_index_for_debug++ << " Run Time: "
             << double(end_clock_for_debug - start_clock_for_debug) / CLOCKS_PER_SEC << "s" << endl;
        cout << "--------------------------------------------------" << endl;
    }
#else
    solve();
#endif
    return 0;
}

Guess you like

Origin blog.csdn.net/m0_43448982/article/details/103842069