• loj#6036 编码


    分析

    考虑trie+2sat

    每次将?=0和?=1的分别插入

    插入串时将这个点的选择状态和前缀的选择状态连关系边

    注意串结束时建一个新点表示当前串

    最后跑2sat即可

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define a(x) x<<1
    #define b(x) x<<1|1
    #define pb push_back
    stack<int>a;
    string s[500100];
    vector<int>v[3000100];
    int id[500100],siz[500100],n,m;
    int trie[3000100][2],cnt,bel[3000100];
    int low[3000100],dfn[3000100],is[3000100],T,sum;
    inline bool cmp(int a,int b){return siz[a]<siz[b];}
    inline void add(int x,int y){v[x].pb(y),v[y^1].pb(x^1);}
    inline void tarjan(int x,int fa){
        dfn[x]=low[x]=++T;
        a.push(x);
        is[x]=1;
        for(int i=0;i<v[x].size();i++)
          if(v[x][i]!=fa){
              if(!dfn[v[x][i]]){
                tarjan(v[x][i],x);
                low[x]=min(low[x],low[v[x][i]]);
              }else if(is[v[x][i]]){
                low[x]=min(low[x],dfn[v[x][i]]);
              }
          }
        if(low[x]==dfn[x]){
          sum++;
          while(1){
              int u=a.top();
              a.pop();
              is[u]=0;
              bel[u]=sum;
              if(u==x)break;
          }
        }
        return;
    }
    inline void ins(int i,int x){
        int p=0,wh,la=0;
        for(int j=0;j<siz[i];j++){
          wh=(s[i][j]-'0');
          if(!trie[p][wh])trie[p][wh]=++cnt;
          la=p,p=trie[p][wh],add(x,a(p));
        }
        trie[la][wh]=++cnt;
        add(x,b(cnt)),add(a(cnt),a(p));
        return;
    }
    int main(){
        int i,j,k,ok;
        scanf("%d",&n);cnt=n;
        for(i=1;i<=n;i++){
          cin>>s[i];
          id[i]=i;
          siz[i]=s[i].length();
        }
        sort(id+1,id+n+1,cmp);
        for(int _=1;_<=n;_++){
          i=id[_],ok=0;
          for(j=0;j<siz[i];j++)
            if(s[i][j]=='?'){
              s[i][j]='0',ins(i,a(i));
              s[i][j]='1',ins(i,b(i));
              ok=1;
              break;
            }
          if(!ok){
              ins(i,a(i));
              add(b(i),a(i));
          }
        }
        for(i=2;i<=(cnt<<1|1);i++)if(!dfn[i])tarjan(i,0);
        for(i=1;i<=cnt;i++)
          if(bel[a(i)]==bel[b(i)]){
              puts("NO");
              return 0;
          }
        puts("YES");
        return 0;
    }
  • 相关阅读:
    Beyond Compare同步功能简介
    CorelDRAW中如何制作表格
    如何解决CorelDRAW中尖突问题
    LCS 最长公共子序列
    Java容器部分用法
    数论知识简易总结
    操作系统的运行环境 中断与有异常
    OS的发展和分类
    操作系统的基本概念
    搭建神经网络的八股
  • 原文地址:https://www.cnblogs.com/yzxverygood/p/11669415.html
Copyright © 2020-2023  润新知