hdu3247 Resource Archiver [kuangbin topic-ac automata]

This question is also very interesting, combining ac automata, dp and the shortest path. This question requires constructing a string that includes all Resource strings and does not contain any virus strings. A string that does not contain any virus can be converted into a node that cannot go to the dictionary tree, so it is natural to think that the key to this question is to transfer from one resource string to another with the shortest new length required. Combining the dictionary tree, moving from one string to another, can it be understood as going from the node pointed to by the last character of the previous string to the node pointed to by the last character of the next string? This turned into a tsp problem to some extent. We first use the shortest path algorithm to find the steps required to transfer all resource strings to another resource string, which is to walk a few steps on the dictionary tree, and then you can dp. Since n is less than 10, we can still use the state pressure mentioned before to put the state that indicates whether 10 strings appear or not in one dimension.
Pay attention to de-duplication of the resource string.

#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <queue>
#include <map>
#include <cstring>
#define fi first
#define se second
#define FIN freopen("in.txt","r",stdin)
#define FIO freopen("out.txt","w",stdout)
#define INF 0x3f3f3f3f
#define per(i,a,n) for(int i = a;i < n;i++)
#define rep(i,a,n) for(int i = n;i > a;i--)
#define pern(i,a,n) for(int i = a;i <= n;i++)
#define repn(i,a,n) for(int i = n;i >= a;i--)
#define fastio std::ios::sync_with_stdio(false)
#define all(a) a.begin(), a.end()
#define ll long long
#define pb push_back
#define endl "\n"
#define pii pair<int,int>
#define sc(n) scanf("%d", &n)
#define CASET int ___T; scanf("%d", &___T); for(int cs=1;cs<=___T;cs++)
template<typename T> inline void _max(T &a,const T b){
    
    if(a<b) a = b;}
template<typename T> inline void _min(T &a,const T b){
    
    if(a>b) a = b;}
using namespace std;
//inline ll read(){
    
    
//    ll a=0;int f=0;char p=getchar();
//    while(!isdigit(p)){f|=p=='-';p=getchar();}
//    while(isdigit(p)){a=(a<<3)+(a<<1)+(p^48);p=getchar();}
//    return f?-a:a;
//}

const int maxn = 300000;

const int maxnode = 2;


int ch[maxn][maxnode]; //字典树
int cnt[maxn];    //单词出现次数
int id[20];
int sz;
int fail[maxn];
int flag[maxn];

char s[1200];
int n,m;
int dp[20][2000];
int dist[100][100];
int temp[maxn];
int in[maxn];
int spfaqu[maxn];
void init()
{
    
    

    sz = 1;
    memset(id,0,sizeof(id));
    memset(flag,0,sizeof(flag));
    memset(ch[0], 0, sizeof(ch[0]));
    memset(cnt,0,sizeof(cnt));
    memset(dp,INF,sizeof(dp));
    cnt[0] = 0;

}

void insert(char str[], int len,int f) //插入字符串
{
    
    
    int u = 0;
    per(i, 0, len)
    {
    
    
        int v = str[i]-'0';
        if (!ch[u][v])
        {
    
    
            memset(ch[sz], 0, sizeof(ch[sz]));
            cnt[sz] = 0;
            ch[u][v] = sz++;
        }
        u = ch[u][v];
    }
    cnt[u]++;
    if(f)
    {
    
    
        if(cnt[u] == 1)
        {
    
    
            dp[n][1<<n] = len;
            id[n++] = u;
        }
    }
    else flag[u] = 1;

    //在这里我们可以建立一个int-string的映射,以通过节点序号得知这个点是哪个单词的结尾
}

void getfail()
{
    
    
    //所有模式串已插入完成
    queue<int> q;
    per(i, 0,maxnode)
    {
    
    
        if (ch[0][i])
        {
    
    
            fail[ch[0][i]] = 0;
            q.push(ch[0][i]);
        }
    }
    while (!q.empty())
    {
    
    
        int now = q.front();
        q.pop();
        per(i, 0,  maxnode)
        {
    
    
            if (ch[now][i])
            {
    
    
                fail[ch[now][i]] = ch[fail[now]][i];
                q.push(ch[now][i]);
            }
            else
                ch[now][i] = ch[fail[now]][i];
        }
        cnt[now] += cnt[fail[now]];
    }
}

void Spfa_ForDist(int s) {
    
    

    int i,j,k,u,v,ndis;
    int head = 0,tail = 0;


    temp[s] = 0;
    spfaqu[head++] = s,in[s] = 1;


    while (tail < head) {
    
    

        u = spfaqu[tail++]; in[u] = 0;
        for ( k = 0; k < 2; ++k)
            if (!flag[ch[u][k]]) {
    
    

                ndis = temp[u] + 1;
                v = ch[u][k];
                if (ndis < temp[v]) {
    
    

                    temp[v] = ndis;
                    if (in[v] == 0)
                        spfaqu[head++] = v,in[v] = 1;
                }
            }
    }
}

void build()
{
    
    
    per(i,0,n)
    {
    
    
        pern(j,0,sz)
        {
    
    
            in[j] = 0;
            temp[j] = INF;
        }
        Spfa_ForDist(id[i]);
        per(j,0,n) dist[i][j] = temp[id[j]];
    }
}

int solve()
{
    
    
    per(i,1,(1<<n))
    {
    
    
        per(j,0,n)
        {
    
    
            if(i&(1<<j))
            {
    
    
                per(k,0,n)
                {
    
    
                    if(!(i&(1<<k)) && dist[j][k]!=INF)
                    {
    
    
                        int nst = i|(1<<k);
                        dp[k][nst] = min(dp[k][nst],dp[j][i]+dist[j][k]);
                    }
                }
            }
        }
    }
    int ans = INF;
    per(i,0,n) ans = min(ans,dp[i][(1<<n)-1]);
    return ans;
}
int main()
{
    
    

    #ifndef ONLINE_JUDGE
        int startTime = clock();
        FIN;
    #endif
    //fastio;
	//忘记初始化是小狗
    //freopen("out.txt","w",stdout);
    //ios::sync_with_stdio(false);
    int _T = 0;
    while(~scanf("%d%d",&n,&m))
    {
    
    
        if(n+m == 0)return 0;
        init();

        int k = n;
        n = 0;
        per(i,0,k){
    
    
            scanf("%s",s);
            insert(s,strlen(s),1);
        }
        per(i,0,m)
        {
    
    
            scanf("%s",s);
            insert(s,strlen(s),0);
        }
        getfail();
        build();
        printf("%d\n",solve());
    }
    #ifndef ONLINE_JUDGE
        printf("\nTime = %dms\n", clock() - startTime);
    #endif
    return 0;
}

Guess you like

Origin blog.csdn.net/qq_39586345/article/details/108568578
Recommended