HDU 3247 Resource Archiver(自动机+状态压缩DP)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3247

题意:给出n个源串,m个病毒串。构造一个串S包含所有的源串且不包含任意病毒串。S的长度最短?

思路:将源串和病毒串都插入trie,建立自动机。BFS得到任意两个源串之间的距离。最后状态压缩DP。





struct node

{

    int next[2],fail,x,y;



    void init()

    {

        next[0]=next[1]=0;

        fail=0;

        x=y=0;

    }

};



node a[N];

int e,n,m;







void insert(char s[],int t)

{

    int i,k,p=0;

    for(i=0;s[i];i++)

    {

        k=s[i]-'0';

        if(a[p].next[k]==0)

        {

            a[e].init();

            a[p].next[k]=e++;

        }

        p=a[p].next[k];

    }

    if(t==-1) a[p].y=1;

    else a[p].x=1<<t;

}



queue<int> Q;



void build()

{

    int i,j,k,p,q;

    FOR0(i,2) if(a[0].next[i]) Q.push(a[0].next[i]);

    while(!Q.empty())

    {

        k=Q.front();

        Q.pop();

        for(i=0;i<2;i++)

        {

            if(a[k].next[i])

            {

                p=a[k].next[i];

                q=a[k].fail;

                Q.push(p);

                a[p].fail=a[q].next[i];

                a[p].x|=a[a[p].fail].x;

                a[p].y|=a[a[p].fail].y;

            }

            else

            {

                q=a[k].fail;

                a[k].next[i]=a[q].next[i];

            }

        }

    }

}



char s[50005];

int p[405][405],mp[405],cnt;

int dis[N];

int f[1030][405];





void BFS(int u)

{

    Q.push(mp[u]);

    int i,j,k;

    FOR0(i,e) dis[i]=INF;

    dis[mp[u]]=0;

    while(!Q.empty())

    {

        k=Q.front();

        Q.pop();



        FOR0(i,2)

        {

            j=a[k].next[i];

            if(dis[j]==INF&&!a[j].y)

            {

                dis[j]=dis[k]+1;

                Q.push(j);

            }

        }

    }

    FOR0(i,cnt) p[u][i]=dis[mp[i]];

}



void DP()

{

    clr(f,-1);

    f[0][0]=0;

    int i,j,k,t;

    FOR0(i,(1<<n)) FOR0(j,cnt) if(f[i][j]!=-1)

    {

        FOR0(k,cnt) if(p[j][k]!=INF)

        {

            t=i|a[mp[k]].x;

            if(f[t][k]==-1||f[t][k]>f[i][j]+p[j][k])

            {

                f[t][k]=f[i][j]+p[j][k];

            }

        }

    }

    int ans=INF,x=(1<<n)-1;

    FOR0(i,cnt) if(f[x][i]!=-1&&f[x][i]<ans)

    {

        ans=f[x][i];

    }

    PR(ans);

}



int main()

{

    while(scanf("%d%d",&n,&m),n||m)

    {

        a[0].init();e=1;

        int i;

        FOR0(i,n) RD(s),insert(s,i);

        FOR0(i,m) RD(s),insert(s,-1);

        build();

        cnt=1;

        FOR0(i,e) if(a[i].x) mp[cnt++]=i;

        FOR0(i,cnt) BFS(i);

        DP();

    }

    return 0;

}

  

你可能感兴趣的:(resource)