bzoj 2938(AC自动机+拓扑排序)

来源:互联网 发布:淘宝客 traceid 编辑:程序博客网 时间:2024/06/06 07:40

传送门
题意:略

构建AC自动机,无限长的安全代码满足能一直在AC自动机上匹配但始终匹配不上任何一个危险串。从根往下dfs(只走不作为危险串结尾的结点),如果能找到一个环,就存在无限长的安全代码,否则不存在。找环用拓扑排序实现。

注意:所有字符串的题,siz,cnt等变量一定千万切记不要错写成char,否则可能会在废掉五六个小时orz。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<queue>using namespace std;const int maxn=3e4+5;int n;char s[maxn];int head[maxn],edge=0,ind[maxn],siz=0;struct EDGE {    int v,nxt;}e[maxn<<1];inline void adde(int u,int v) {    e[edge].nxt=head[u],e[edge].v=v,head[u]=edge++;}struct AC_automation {    int ch[maxn][2],fail[maxn];    bool vis[maxn],end[maxn];    inline void init() {        memset(ch,0,sizeof(ch)),        memset(vis,false,sizeof(vis)),        memset(end,false,sizeof(end));    }    inline void insert(char *s) {        int len=strlen(s),now=0;        for (int i=0;i<len;++i) {            int x=s[i]-'0';            if (!ch[now][x]) ch[now][x]=++siz;            now=ch[now][x];        }        end[now]=1;    }    inline void build() {        queue<int> q;        while (!q.empty()) q.pop();        if (ch[0][0]) q.push(ch[0][0]);        if (ch[0][1]) q.push(ch[0][1]);        while (!q.empty()) {            int now=q.front();q.pop();            for (int i=0;i<=1;++i) {                if (!ch[now][i]) {ch[now][i]=ch[fail[now]][i];continue;}                fail[ch[now][i]]=ch[fail[now]][i];                if (end[fail[ch[now][i]]]) end[ch[now][i]]=1;                q.push(ch[now][i]);            }        }    }    void dfs(int p) {        vis[p]=true;        for (int i=0;i<=1;++i) {            adde(p,ch[p][i]),++ind[ch[p][i]];            if (!vis[ch[p][i]]&&!end[ch[p][i]]) dfs(ch[p][i]);        }    }}AC;inline bool Topo() {    queue<int> q;    int tim=0;    while (!q.empty()) q.pop();    for (int i=0;i<=siz;++i)        if (!ind[i]) q.push(i);    while (!q.empty()) {        int p=q.front();q.pop();        ++tim;        for (int i=head[p];~i;i=e[i].nxt) {            int v=e[i].v;            --ind[v];            if (!ind[v]) q.push(v);        }    }    return tim==siz+1;//found circle->true->NIE    //why +1:0(root) is a node as well}int main() {//  freopen("bzoj 2938.in","r",stdin);    AC.init();    memset(head,-1,sizeof(head));    memset(ind,0,sizeof(ind));    scanf("%d",&n);    while (n--) {        scanf("%s",s);        AC.insert(s);    }    AC.build();    AC.dfs(0);    puts(Topo()?"NIE":"TAK");    return 0;}
原创粉丝点击