羅区2444:ウイルス

羅区2444:ウイルス

質問の意味:

  • ウイルスと呼ばれるn個のバイナリ文字列があります。
  • したがって、この構成では、バイナリ文字列にウイルスが存在することを、バイナリ文字列を構築します。
  • 答えは、このような文字列を構築できるかどうか。

アイデア:

  • ACオートマトン。
  • ACオートマトンは、マルチパターンマッチングデータ構造です。
  • 私たちは最初の構文\(トライ\)木とビルド\(\不合格)のポインタを。
  • この時間\(トライ\)ツリーはなくなりました\(トライ\)木、およびいくつかの添加後、\(\不合格)ポインタは、有向グラフになります。
  • そのような無限の文字列がある場合は、何のウイルスは、彼の子供の文字列ではないことを確認すること、そして何が起こるのだろうか?
  • 彼は無限オートマトンにサークルでラウンド行くことになるので、文字列は、無限に長い構築ので、自動機に一致するように、この文字列を取り、関係なくはどのようなもの、また、ウイルスの文字列に端位置ではありません。
  • 質問はそう:
    • このリングノードなしAC自動マシン上のリングを入手文字列ウイルスの終わりです。
  • ノードという注意\(\失敗)ノードが最後であれば、ノードが、その後、彼はまた、自己エンド・ノードでなければなりません。
  • 見るためにマップを描きます
#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e4 + 10;
char s[maxn];
int n;

struct AC_Automaton
{
    int trie[maxn][5];
    int val[maxn];
    int fail[maxn];
    int tot;

    void ins(char *str)
    {
        int len = strlen(str), p = 0;
        for(int k = 0; k < len; k++)
        {
            int ch = str[k] - '0';
            if(trie[p][ch] == 0) trie[p][ch] = ++tot;
            p = trie[p][ch];
        }
        val[p] = 1;
    }

    void build()
    {
        queue<int> q;
        for(int i = 0; i < 2; i++)
        {
            if(trie[0][i])
            {
                //第二层指向根节点
                fail[trie[0][i]] = 0;
                q.push(trie[0][i]);
            }
        }
        while(q.size())
        {
            int x = q.front(); q.pop();
            for(int i = 0; i < 2; i++)
            {
                if(trie[x][i])
                {
                    fail[trie[x][i]] = trie[fail[x]][i];
                    val[trie[x][i]] |= val[fail[trie[x][i]]];
                    q.push(trie[x][i]);
                }
                else trie[x][i] = trie[fail[x]][i];
            }
        }
    }

    bool v1[maxn];
    
    void dfs(int x)
    {
        if(v1[x])
        {
            puts("TAK");
            exit(0);
        }
        if(val[x]) return;
        v1[x] = 1;
        if(trie[x][0]) dfs(trie[x][0]);
        if(trie[x][1]) dfs(trie[x][1]);
        v1[x] = 0;
    }
}AC;


int main()
{
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%s", s);
        AC.ins(s);
    } AC.build();
    AC.dfs(0); //从字典树根节点开始找环
    puts("NIE"); //不存在无限的串
    return 0;
}

おすすめ

転載: www.cnblogs.com/zxytxdy/p/12233485.html