HDU 2296 Ring -----------AC自动机,其实我想说的是怎么快速打印字典序最小的路径

大冥神的代码,以后能贴的机会估计就更少了。。。。所以本着有就贴的好习惯,= =。。。。直接贴

#include <bits/stdc++.h>
using LL = long long ;
#define ALL(v) (v).begin(),(v).end()
#define showtime fprintf(stderr,"time = %.15f\n",clock() / (double)CLOCKS_PER_SEC)

char str[100][11];
int n,m;
int weight[100];

const int N = 10 * 100 + 5;
int go[N][26],val[N],fail[N],tot;

int get_node() {
    memset(go[tot],-1,sizeof(go[tot]));
    val[tot] = 0;
    return tot ++;
}

int dp[50 + 1][N],pre[50 + 1][N],pc[50 + 1][N];
std::vector<int> order[50 + 1];

void insert(char *s,int w) {
    int u = 0;
    for ( ; *s; ++ s) {
        int c = *s - 'a';
        if (go[u][c] == -1) 
            go[u][c] = get_node();
        u = go[u][c];
    }
    val[u] += w;
}

std::string work() {
    tot = 0;
    get_node();
    for (int i = 0; i < m; ++ i) {
        insert(str[i],weight[i]);
    }
    std::vector<int> vec{0};
    fail[0] = -1;
    for (int I = 0; I < (int)vec.size(); ++ I) {
        int u = vec[I];
        for (int c = 0; c < 26; ++ c) {
            if (go[u][c] == -1) continue;
            int v = go[u][c];
            int f = fail[u];
            while (f != -1 && go[f][c] == -1) f = fail[f];
            fail[v] = f == -1 ? 0 : go[f][c];
            vec.push_back(v);
        }
    }
    for (int I = (int)vec.size() - 1; I >= 0; -- I) {
        int u = vec[I];
        for (int c = 0; c < 26; ++ c) {
            int f = u;
            while (f != -1 && go[f][c] == -1) f = fail[f];
            go[u][c] = f == -1 ? -1 : go[f][c];
        }
        for (int f = fail[u]; f != -1; f = fail[f]) {
            val[u] += val[f];
        }
    }
    memset(dp,-1,sizeof(dp));
    memset(pre,-1,sizeof(pre));
    dp[0][0] = 0;
    for (int i = 0; i <= n; ++ i) {
        order[i].clear();
    }
    order[0].push_back(0);
    for (int i = 0; i < n; ++ i) {
        for (int u : order[i]) {
            for (int c = 0; c < 26; ++ c) {
                if (go[u][c] == -1) continue;
                int v = go[u][c];
                dp[i + 1][v] = std::max(dp[i + 1][v],dp[i][u] + val[v]);
            }
        }
        for (int u : order[i]) {
            for (int c = 0; c < 26; ++ c) {
                if (go[u][c] == -1) continue;
                int v = go[u][c];
                if (dp[i + 1][v] == dp[i][u] + val[v] && pre[i + 1][v] == -1) {
                    pre[i + 1][v] = u;
                    pc[i + 1][v] = c;
                    order[i + 1].push_back(v);
                }
            }
        }
    }

    int ai = 0,au = 0;
    for (int i = 0; i <= n; ++ i) {
        for (int u : order[i]) {
            if (dp[i][u] > dp[ai][au]) {
                ai = i;
                au = u;
            }
        }
    }
    std::string ret;
    while (ai) {
        ret.push_back(pc[ai][au] + 'a');
        au = pre[ai][au];
        -- ai;
    }
    std::reverse(ALL(ret));
    return ret;
}

int main() {
    int cas;
    scanf("%d",&cas);
    while (cas--) {
        scanf("%d%d",&n,&m);
        for (int i = 0; i < m; ++ i) {
            scanf("%s",str[i]);
        }
        for (int i = 0; i < m; ++ i) {
            scanf("%d",weight + i);
        }
        printf("%s\n",work().c_str());
    }
}

  

posted @ 2016-07-17 16:40  92度的苍蓝  阅读(284)  评论(0编辑  收藏  举报
http://images.cnblogs.com/cnblogs_com/Running-Time/724426/o_b74124f376fc157f352acc88.jpg