码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 2296 Ring (AC自动机 + DP)

时间:2015-08-15 18:20:36      阅读:156      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:Ring


解析:m个有价值的串,字符串s在字符串str中的价值 = s在str中出现的次数 × s的价值。问价值最大的长度为n的串是什么。

本题需要输出字典序最小的

在DP的时候开一个数组记录结果即可。



AC代码:

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

int a[110];
int dp[55][1110];
char str[55][1110][55];

bool cmp(char s1[], char s2[]){
    int len1 = strlen(s1);
    int len2 = strlen(s2);
    if(len1 != len2) return len1 < len2;
    else return strcmp(s1, s2) < 0;
}

const int INF = 0x3f3f3f3f;
struct Trie{
    int next[1110][26], fail[1110], end[1110];
    int root, L;
    int newnode(){
        for(int i=0; i<26; i++) next[L][i] = -1;
        end[L++] = -1;
        return L-1;
    }
    void init(){
        L = 0;
        root = newnode();
    }
    void insert(char buf[], int id){
        int len = strlen(buf);
        int now = root;
        for(int i=0; i<len; i++){
            if(next[now][buf[i] - 'a'] == -1)
                next[now][buf[i] - 'a'] = newnode();
            now = next[now][buf[i] - 'a'];
        }
        end[now] = id;
    }
    void build(){
        queue<int> Q;
        fail[root] = root;
        for(int i=0; i<26; i++){
            if(next[root][i] == -1)
                next[root][i] = root;
            else{
                fail[next[root][i]] = root;
                Q.push(next[root][i]);
            }
        }
        while(!Q.empty()){
            int now = Q.front();
            Q.pop();
            for(int i=0; i<26; i++){
                if(next[now][i] == -1)
                    next[now][i] = next[fail[now]][i];
                else{
                    fail[next[now][i]] = next[fail[now]][i];
                    Q.push(next[now][i]);
                }
            }
        }
    }
    int solve(int n){
        for(int i=0; i<=n; i++)
            for(int j=0; j<L; j++)
                dp[i][j] = -INF;
        dp[0][0] = 0;
        strcpy(str[0][0], "");
        char ans[55];
        strcpy(ans, "");
        int Max = 0;
        char tmp[55];
        for(int i=0; i<n; i++)
            for(int j=0; j<L; j++)
                if(dp[i][j] >= 0){
                    strcpy(tmp, str[i][j]);
                    int len = strlen(tmp);
                    for(int k=0; k<26; k++){
                        int nxt = next[j][k];
                        tmp[len] = 'a' + k;
                        tmp[len+1] = 0;
                        int tt = dp[i][j];
                        if(end[nxt] != -1) tt += a[ end[nxt] ];
                        if(dp[i+1][nxt] < tt || (dp[i+1][nxt] == tt && cmp(tmp, str[i+1][nxt]))){
                            dp[i+1][nxt] = tt;
                            strcpy(str[i+1][nxt], tmp);
                            if(tt > Max || (tt == Max && cmp(tmp, ans))){
                                Max = tt;
                                strcpy(ans, tmp);
                            }
                        }
                    }

                }
        printf("%s\n", ans);
    }
};

char buf[60];
Trie ac;
int main(){
//    freopen("in.txt", "r", stdin);

    int T;
    int n, m;
    scanf("%d", &T);
    while(T--){
        scanf("%d%d", &n, &m);
        ac.init();
        for(int i=0; i<m; i++){
            scanf("%s", buf);
            ac.insert(buf, i);
        }
        for(int i=0; i<m; i++)
            scanf("%d", &a[i]);
        ac.build();
        ac.solve(n);
    }
    return 0;
}




版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU 2296 Ring (AC自动机 + DP)

标签:

原文地址:http://blog.csdn.net/u013446688/article/details/47683659

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!