hdoj3247

注意bfs fail路线的花费。如果一个点nex没有,才能走fail,走到的是fail后再走那个数的位置。花费为1.不能用dfs。bfs首次到就是最近。不过串不能包含。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <iomanip>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <cassert>
#include <stack>
#include <bitset>
#define mkp make_pair
using namespace std;
const double EPS=1e-12;
typedef long long lon;
const lon SZ=60010,SSZ=12,APB=2,one=1;
const lon INF=0x7FFFFFFF,mod=1000000007;
lon n,m,mk[SZ],nex[SZ][APB],fail[SZ];
int cnt,endpos[SSZ],dst[SSZ][SSZ];
int dtb[SZ],dp[1030][SSZ],len[SSZ];
int bel[SZ];
char ch[SZ];

void add(int type,int id)
{
    int cur=0;
    for(int i=1;ch[i];++i)
    {
        int c=ch[i]-'0';
        if(!nex[cur][c])nex[cur][c]=++cnt;
        cur=nex[cur][c];
    }
    if(type)mk[cur]=1;
    else endpos[id]=cur,bel[cur]=id;
}

void build()
{
    queue<int> q;
    q.push(0);
    for(;q.size();)
    {
        int fr=q.front();
        q.pop();
        for(int i=0;i<APB;++i)
        {
            int t=nex[fr][i];
            if(t)
            {
                if(!fr)fail[t]=0;
                else
                {
                    int u=fail[fr];
                    for(;u&&!nex[u][i];u=fail[u]);
                    u=nex[u][i];
                    fail[t]=u;
                    mk[t]|=mk[u];
                }
                q.push(t);
            }
        }
    }
}

void bfs(int x)
{
    dtb[x]=0;
    queue<int> q;
    q.push(x);
    for(;q.size();)
    {
        int fr=q.front();
        q.pop();
        for(int i=0;i<APB;++i)
        {
            int t=nex[fr][i];
            if(t)
            {
                if(dtb[t]>dtb[fr]+1&&!mk[t])
                {
                    q.push(t);
                    dtb[t]=dtb[fr]+1;
                }
            }
            else
            {
                int u=fail[fr];
                for(;u&&!nex[u][i];u=fail[u]);
                t=nex[u][i];
                if(dtb[t]>dtb[fr]+1&&!mk[t])
                {
                    q.push(t);
                    dtb[t]=dtb[fr]+1;
                }
            }
        }
    }
}

void init()
{
    for(int i=0;i<n;++i)
    {
        //cin>>ch+1;
        scanf(" %s",ch+1);
        len[i]=strlen(ch+1);
        add(0,i);
    }
    for(int i=0;i<m;++i)
    {
        scanf(" %s",ch+1);
        add(1,-1);
    }
    build();
    for(int i=0;i<n;++i)
    {
        for(int j=0;j<=cnt;++j)
        dtb[j]=INF/2;
        int sta=0;
        bfs(endpos[i]);
        for(int j=0;j<n;++j)
        {
            dst[i][j]=dtb[endpos[j]];
        }
    }
}

int dfs(int sta,int last)
{
    if(dp[sta][last])return dp[sta][last];
    else
    {
        int res=INF;
        for(int i=0;i<n;++i)
        {
            if((sta&(1<<i))&&i!=last)
            {
                res=min(res,dfs(sta^(1<<last),i)+dst[i][last]);
            }
        }
        return dp[sta][last]=res;
    }
}

void work()
{
    for(int i=0;i<n;++i)
    {
        dp[1<<i][i]=len[i];
    }
    int res=INF;
    for(int i=0;i<n;++i)
    {
        res=min(res,dfs((1<<n)-1,i));
        //cout<<"i: "<<dfs((1<<n)-1,i)<<" "<<dst[0][1]<<" "<<dst[1][0]<<endl;
    }
    cout<<res<<endl;
}

void release()
{
    for(int i=0;i<=cnt;++i)
    {
        mk[i]=0;
        memset(nex[i],0,sizeof(nex[i]));
        fail[i]=0;
        bel[i]=-1;    
    }
    cnt=0;
    for(int i=0;i<(1<<n);++i)
    {
        memset(dp[i],0,sizeof(dp[i]));
    }
}

int main()
{
    //std::ios::sync_with_stdio(0);
    //freopen("d:\\1.txt","r",stdin);
    int casenum;
    //memset(bel,-1,sizeof(bel));
    //cin>>casenum;
    //cout<<casenum<<endl;
    //for(int time=1;time<=casenum;++time)
    for(int time=1;cin>>n>>m,n;++time)
    {
        init();
        work();
        release();
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/gaudar/p/10773907.html