HDU 2296 Ring (AC自动机 + DP)

题目链接: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;
}

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

时间: 2024-10-24 22:36:55

HDU 2296 Ring (AC自动机 + DP)的相关文章

HDU 2296 Ring AC自动机 + DP

题意:给你n个模式串,每个模式串有一个得分,让你构造出一个长度为N之内且分数最高的文本串;输出字典序列最小的. 解题思路:  AC自动机 + DP , 不过要输出字典序列最小,多开一个 一个三维字符串来辅助二维DP(新思路) , DP[i][j] ,表示到i位置状态为j的最大得分. 解题代码: 1 // File Name: temp.cpp 2 // Author: darkdream 3 // Created Time: 2014年09月11日 星期四 15时18分4秒 4 5 #inclu

HDU 2296 Ring [AC自动机 DP 打印方案]

Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3536 Accepted Submission(s): 1153 Problem Description For the hope of a forever love, Steven is planning to send a ring to Jane with a romantic

[hdu2296]Ring(AC自动机+dp)

题意:你M个单词构成一个词典,每个单词有一个权值(单词出现多次算多个权值),现在要你构造一个不超过长度N的字符串,使得该字符串权值最大.如果出现多个答案,输出最短的,如果依然有多解,输出字典序最小的. 解题关键:最典型的AC自动机上跑dp. 令$dp[i][j] = x$表示走了i步到达j点的最大价值,则 转移方程:$dp[i][j] = \max (dp[i][j],dp[i-1][k] + val[j])$ $val[i]$代表以某前缀的价值总和. 注意这里是多对多的关系,需用从遍历起点时更

hdu 2296 aC自动机+dp(得到价值最大的字符串)

Ring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3180    Accepted Submission(s): 1033 Problem Description For the hope of a forever love, Steven is planning to send a ring to Jane with a rom

hdu 2457 AC自动机+dp

DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2004    Accepted Submission(s): 1085 Problem Description Biologists finally invent techniques of repairing DNA that contains segments c

HDU 3341 Lost&#39;s revenge AC自动机+dp

Lost's revenge Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Total Submission(s): 3757    Accepted Submission(s): 1020 Problem Description Lost and AekdyCoin are friends. They always play "number game"(A bor

Hdu 3341 Lost&#39;s revenge (ac自动机+dp+hash)

题目大意: 给出很多个DNA串,每一个串的价值为1,最后给出一个长串,要你重新排列最后的串使之它所有的子串的权值和最大. 思路分析: 最先容易想到的思路就是搜!管她3721..直接一个字符一个字符的码,然后在AC自动机上判断最后的权值.TLE哟. 然后发现搜过不去,那就dp咯.再容易想到的就是dp[i][a][b][c][d] 表示此时遍历AC自动机的节点在i,然后构成了a个A,b个G,c个C,d个T的权值. 再一看内存,500*40*40*40*40...然后...就没有然后了 再想,因为它说

hdu 2825 Wireless Password(ac自动机&amp;dp)

Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4022    Accepted Submission(s): 1196 Problem Description Liyuan lives in a old apartment. One day, he suddenly found that there

hdu 4878 ZCC loves words(AC自动机+dp+矩阵快速幂+中国剩余定理)

hdu 4878 ZCC loves words(AC自动机+dp+矩阵快速幂+中国剩余定理) 题意:给出若干个模式串,总长度不超过40,对于某一个字符串,它有一个价值,对于这个价值的计算方法是这样的,设初始价值为V=1,假如这个串能匹配第k个模式串,则V=V*prime[k]*(i+len[k]),其中prime[k]表示第k个素数,i表示匹配的结束位置,len[k]表示第k个模式串的长度(注意,一个字符串可以多次匹配同意个模式串).问字符集为'A'-'Z'的字符,组成的所有的长为L的字符串,

HDU 2243 考研路茫茫――单词情结 (AC自动机 + dp)

HDU 2243 考研路茫茫――单词情结 题意:给定一些词根,如果一个单词包含有词根,则认为是有效的.现在问长度不超过L的单词里面,有多少有效的单词? 思路:这道题和POJ 2778是同样的思路.POJ 2778是要找出长度为L的单词里面有多少无效的单词.那么根据同样的方法构造矩阵,然后所有无效的单词个数为 A + A^2 + ... + A^l 个.而所有单词的个数为26 + 26^2 + - + 26^l 个.两个减一下即为答案. 矩阵连乘求和:I + A^2 + A^3 + ... + A