• BZOJ 2938 [POI2000]病毒 (剪枝/A*迭代搜索)


    LOJ BZOJ

    题目大意:给你一些模式串,问是否存在一个无限长的文本串,不包含任何一个给定的模式串

    并没有想到去模拟合法的文本串在模式串的Trie图上匹配的过程..我好菜啊

    如果一个字符串合法,那么它的每个子串都不是任何一个模式串的结尾,即沿着Fail链跳到根的每个点都不是结尾

    一个合法文本串在模式串构成的Trie图上匹配的过程中,会不断沿着一个环去跳

    如果一个环合法,那么这个环需要满足环上每个点,以及根节点到第一个接触到环的路径上的每个点,都合法

    找合法环的过程中,可以用类似于tarjan边双的方法,用两个数组记录那些点被访问过,以及那些点在栈中

     1 #include <queue>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 #define NN 30010
     6 #define ll long long 
     7 #define uint unsigned int
     8 #define ull unsigned long long 
     9 #define inf 0x3f3f3f3f
    10 #define idx(x) (x-'0')
    11 using namespace std;
    12 
    13 int n;
    14 char str[NN];
    15 int head[NN],nt[NN],vis[NN],use[NN],cte;
    16 struct Edge{int to,nxt;}edge[NN*2];
    17 void ae(int u,int v){
    18     cte++;edge[cte].nxt=head[u];
    19     edge[cte].to=v,head[u]=cte;
    20 }
    21 struct AC{
    22 int fail[NN],g[NN],ch[NN][2],ed[NN],tot;
    23 void Build_Trie(char *a,int len)
    24 {
    25     int x=0;
    26     for(int i=1;i<=len;i++){
    27         if(!ch[x][idx(a[i])])
    28             ch[x][idx(a[i])]=++tot;
    29         x=ch[x][idx(a[i])];
    30     }ed[x]=1;
    31 }
    32 void Build_Fail()
    33 {
    34     queue<int>q;
    35     if(ch[0][0]) q.push(ch[0][0]);
    36     if(ch[0][1]) q.push(ch[0][1]);
    37     while(!q.empty())
    38     {
    39         int x=q.front();q.pop();
    40         ae(fail[x],x);
    41         for(int i=0;i<2;i++){
    42             if(ch[x][i]){
    43                 fail[ch[x][i]]=ch[fail[x]][i];
    44                 q.push(ch[x][i]);
    45             }else{
    46                 ch[x][i]=ch[fail[x]][i];
    47             }
    48         }
    49     }
    50     q.push(0);
    51     while(!q.empty())
    52     {
    53         int x=q.front();q.pop();
    54         for(int j=head[x];j;j=edge[j].nxt){
    55             int v=edge[j].to;
    56             if(ed[v]||g[x]) g[v]=1;
    57             q.push(v);
    58         }
    59     }
    60 }
    61 int find_cir(int x)
    62 {   
    63     if(vis[x]) return 0;
    64     vis[x]=1,use[x]=1;
    65     int ans=0;
    66     for(int i=0;i<2;i++){
    67         if(use[ch[x][i]]) return 1;
    68         if(!g[ch[x][i]])
    69             ans=find_cir(ch[x][i]);
    70         if(ans) return 1;
    71     }use[x]=0;return 0;
    72 }
    73 void solve()
    74 {
    75     for(int i=1;i<=n;i++){
    76         scanf("%s",str+1);
    77         int len=strlen(str+1);
    78         Build_Trie(str,len);
    79     }Build_Fail();
    80     int ans=0;
    81     ans=find_cir(ch[0][0]);
    82     if(ans){printf("TAK
    ");return;}
    83     memset(vis,0,sizeof(vis));
    84     ans=find_cir(ch[0][1]);
    85     if(ans){printf("TAK
    ");return;}
    86     printf("NIE
    ");
    87 }
    88 }ac;
    89 
    90 int main()
    91 {
    92     //freopen("t2.in","r",stdin);
    93     scanf("%d",&n);
    94     ac.solve();
    95     return 0;
    96 }
  • 相关阅读:
    电磁学讲义3:电场
    电磁学讲义2:库仑定律
    电磁学讲义1:静电的基本现象
    安卓(Android)手机如何安装APK?
    理论物理极础9:相空间流体和吉布斯-刘维尔定理
    物理学家的LOGO
    Zhulina 的高分子刷理论
    一步一步学Silverlight 2系列(5):实现简单的拖放功能
    地图上显示X,Y 坐标代码
    一步一步学Silverlight 2系列(4):鼠标事件处理
  • 原文地址:https://www.cnblogs.com/guapisolo/p/10012478.html
Copyright © 2020-2023  润新知