zoukankan      html  css  js  c++  java
  • [HDU3247]Resource Archiver

      AC自动机+状压DP

      首先对所有串建AC自动机,然后对于每个资源串,算出从串末走到其他资源串末所需的距离(中途避开非法点)

      也就是算出两两间的距离。。。然后就变成旅行商问题了。

      计算距离的时候要考虑一下。。直接从末尾走的话可能求出来的并不是最短路

      所以要从fail和ch(就是虚边和实边)一起转移,走实边的话加进队列,虚边只能更新距离(不然可能非法)

      但似乎正确性存疑?。。可能存在 三个资源串,分别按照最短距离拼在一起后会包含病毒串 的情况。。。

      反正我的程序会炸,但网上一些标程没事= =。。。另外本题数据极弱,随机数据就能艹翻一大坨标程系列

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 #define next NEXT
      5 using namespace std;
      6 const int maxn=60023,inf=1002333333;
      7 int ch[maxn][2],next[maxn][2],fail[maxn],tot;
      8 bool gg[maxn],uu[maxn];
      9 int f1[maxn];
     10 char s[maxn],mp[11][1023];int len[11],ed[11];
     11 int d[11][11],dis[maxn],d1[maxn];
     12 int f[1026][11],two[11];
     13 int dl[maxn],l,r;
     14 int i,j,k,n,m;
     15 
     16 inline void getf1(int x){
     17     int i,p=0;f1[1]=0;
     18     for(i=2;i<=len[x];i++){
     19         while(p&&mp[x][i]!=mp[x][p+1])p=f1[p];
     20         p+=mp[x][i]==mp[x][p+1],f1[i]=p;
     21     }
     22 }
     23 inline bool check(int x,int y){
     24     int i,p=0;
     25     for(i=1;i<=len[y];i++){
     26         while(p&&mp[y][i]!=mp[x][p+1])p=f1[p];
     27         p+=mp[y][i]==mp[x][p+1];
     28         if(p==len[x])return 1;
     29     }
     30     return 0;
     31 }
     32 
     33 inline void trie(int n,int id){
     34     int i,p=0;
     35     for(i=1;i<=n;i++){
     36         s[i]-='0';
     37         if(!ch[p][s[i]])ch[p][s[i]]=++tot,p=tot;
     38         else p=ch[p][s[i]];
     39     }
     40     if(!id)gg[p]=1;else ed[id]=p;//printf("  gg:%d
    ",p);
     41 }
     42 inline void getfail(){
     43     int i,now,p,j;l=0,r=1,dl[1]=0;
     44     while(l<r){
     45         now=dl[++l];
     46         for(i=0;i<2;/*printf("%d %d  next:%d
    ",now,i,next[now][i]),*/i++)if(ch[now][i]){
     47             dl[++r]=j=next[now][i]=ch[now][i];
     48             for(p=fail[now];p&&!ch[p][i];p=fail[p]);
     49             if(!now)fail[j]=0;else fail[j]=ch[p][i];
     50             gg[j]|=gg[fail[j]];
     51         }else{
     52             for(p=fail[now];p&&!ch[p][i];p=fail[p]);
     53             next[now][i]=ch[p][i];
     54         }
     55     }
     56     for(i=0;i<=tot;i++)if(gg[i])
     57     for(j=0/*,printf("!! gg:%d
    ",i)*/;j<2;j++)if(ch[i][j])gg[ch[i][j]]=1;
     58 }
     59 inline void bfs(int s){
     60     memset(dis,255,(tot+1)<<2);memset(uu,0,tot+1);
     61     int l=0,r=0,i,now,j;
     62     if(!gg[s])dl[++r]=s,dis[s]=d1[s]=0,uu[s]=1;
     63     for(i=fail[s];i;i=fail[i])if(!gg[i])dis[i]=0;
     64     while(l<r){
     65         now=dl[++l];
     66         for(i=0;i<2;i++)if(!gg[next[now][i]]&&!uu[next[now][i]]){
     67             dl[++r]=next[now][i];uu[dl[r]]=1;d1[dl[r]]=d1[now]+1;
     68             if(dis[dl[r]]==-1)dis[dl[r]]=d1[dl[r]];
     69             for(j=fail[dl[r]];j;j=fail[j])if(dis[j]==-1)dis[j]=dis[dl[r]];
     70 //            if(s==16)printf("walk:%d->%d
    ",now,next[now][i]);
     71         }
     72     }
     73 //    if(s==16)
     74 //        for(i=0;i<=tot;i++)printf("    %d->%d %d
    ",s,i,dis[i]);
     75 }
     76 int main(){
     77     freopen("in.txt","r",stdin);
     78     for(i=two[0]=1;i<=10;i++)two[i]=two[i-1]<<1;
     79     for(scanf("%d%d",&n,&m);n&&m;scanf("%d%d",&n,&m)){
     80         memset(ch,0,(tot+1)<<3),memset(next,0,(tot+1)<<3),memset(fail,0,(tot+1)<<2),
     81         memset(gg,0,tot+1),tot=0;
     82         
     83         for(i=1;i<=n;i++)
     84             scanf("%s",mp[i]+1),mp[i][0]='%',len[i]=strlen(mp[i])-1;
     85         for(i=1;i<n;i++)for(j=i+1;j<=n;j++)if(len[i]>len[j])
     86             swap(len[i],len[j]),swap(mp[i],mp[j]);
     87         
     88         for(i=1;i<n;i++){
     89             getf1(i);
     90             for(j=i+1;j<=n;j++)if(check(i,j)){gg[i]=1;/*printf("%d in %d
    ",i,j);*/break;}
     91         }
     92         int n1=0;
     93         for(i=1;i<=n;i++)if(!gg[i])n1++,memcpy(mp[n1],mp[i],len[i]+1),len[n1]=len[i];//,printf("%s
    ",mp[n1]);
     94         memset(gg,0,n+1);
     95         
     96         
     97         for(i=1;i<=n1;i++)memcpy(s,mp[i],len[i]+1),trie(len[i],i);
     98         for(i=1;i<=m;i++)scanf("%s",s+1),s[0]='%',trie(strlen(s)-1,0);
     99         getfail();
    100         
    101         for(i=1;i<=n1;puts(""),i++){
    102             bfs(ed[i]);
    103             for(j=1;j<=n1;/*printf("%s-->%s  %d
    ",mp[i]+1,mp[j]+1,d[i][j]),*/j++)if(dis[ed[j]]!=-1)d[i][j]=dis[ed[j]];else d[i][j]=inf;
    104         }
    105         
    106         int mx=1<<n1;
    107         for(i=0;i<mx;i++)memset(f[i],50,(n1+1)<<2);
    108         for(i=1;i<=n1;i++)f[two[i-1]][i]=len[i];
    109         for(i=1;i<mx;i++){
    110             for(j=1;j<=n1;j++)if(i&two[j-1])
    111             for(k=1;k<=n1;k++)if(k!=j&&(i&two[k-1])&&d[k][j]<inf)
    112                 f[i][j]=min(f[i][j],f[i^two[j-1]][k]+d[k][j]);
    113         }
    114         int ans=inf;
    115         for(i=1;i<=n1;i++)ans=min(ans,f[mx-1][i]);
    116     }
    117     return 0;
    118 }
    View Code
  • 相关阅读:
    数据降维和可视化
    聚类
    支持向量机的实现
    支持向量机核函数
    支持向量基
    倾斜类误差度量
    构建垃圾邮件分类器
    POJ 2955 Brackets (区间dp入门)
    POJ 3126 Prime Path (bfs+欧拉线性素数筛)
    POJ 1426 Find The Multiple (dfs??!!)
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5341133.html
Copyright © 2011-2022 走看看