P2444 [POI2000]病毒

P2444 [POI2000]病毒
这道题直接输出都可以得60分,如果再写个随机算法,那么就可以用O(1)的时间复杂度解决这道题
首先看到这到题,不难想到暴力去枚举每一位,然后再用AC自动机,因为每个点最多只会被访问一次,所以时间复杂度可以道玄学的O(n)
代码

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<queue>
using namespace std;
const int N = 1e5 + 5;

char str[N];
int tr[N][2], cnt[N], net[N], idx;
bool vis[N];
queue<int> q;

void insert()
{
    int p = 0;
    for (int i = 0; str[i]; i++)
    {
        int t = str[i] - '0';
        if (!tr[p][t])
            tr[p][t] = ++idx;
        p = tr[p][t];
    }
    cnt[p] = 1;
}

void build()
{
    if (tr[0][0])
        q.push(tr[0][0]);
    if (tr[0][1])
        q.push(tr[0][1]);
    while (!q.empty())
    {
        int t = q.front();
        q.pop();
        for (int i = 0; i < 2; i++)
        {
            int p = tr[t][i];
            if (!p)
                tr[t][i] = tr[net[t]][i];
            else 
            {
                net[p] = tr[net[t]][i];
                q.push(p);
            }
        }
    }
}

void dfs(int j)
{
    for (int i = 0; i < 2; i++)
    {
        bool flag = false;
        int t = tr[j][i];
        if (vis[t])
        {
            printf("TAK");
            exit(0);
        }
        while (t)
        {
            if (cnt[t])
                flag = true;
            t = net[t];
        }
        if (!flag)
        {
            vis[tr[j][i]] = true;
            dfs(tr[j][i]);
            vis[tr[j][i]] = false;
        }
    }
}

int main()
{
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++)
    {
        scanf("%s", &str);
        insert();
    }
    build();
    dfs(0);
    printf("NIE");
    return 0;
}
posted @ 2021-01-03 22:16  DSHUAIB  阅读(92)  评论(0)    收藏  举报