HDU 2296 Ring(AC自动机+DP)
http://acm.hdu.edu.cn/showproblem.php?pid=2296
题意:
给你M个单词构成一个词典,每个单词有一个权值(单词出现多次算多个权值),现在要你构造一个不超过长度N的字符串,使得该字符串权值最大。如果出现多个答案,输出最短的,如果依然有多解,输出字典序最小的。
分析:
本题和之前几题类似。不过注意这题的AC自动机要用match, match[i]表示i节点的后缀单词权值总和.后缀单词指的是:所有可以做i节点表示的串的后缀的单词.
令dp[i][j]=x表示当前在i点走过了长j的路所生产的最大权值为x. 再用string path[i][j]来保存那个具有最大权值的最优字符串即可.不过要注意如果最后算的的最大权值是0,那么要输出空串.因为空串最短.
dp[i][j] = max(dp[k][j-1]+match[i]) 若dp[i][j]更新的时候,path[i][j]也要看看是否需要更新成:
if(path[i][j]!=””)path[i][j] = better(path[i][j] , path[k][j-1]+”x”)x字符表示从k走到i的那条边的字符是x.
初值path=空串,dp[0][0]=0.
注意:做这题的时候出现了几个错误的地方.
首先对于dp[i][j]不可达的节点一定要置-1,不能置1
其次对于当dp[ch[k][j]][len + 1]
还有HDU提交这题的时候我一直编辑错误,不知道错在哪里?后来不得不改掉一些函数了.后来经过无数次的测试,发现少些了#include
AC代码:
#include
#include
#include
#include
#include
#include
#include
using namespace std;
int N,M;
const int maxnode=1000+100;
const int sigma_size=26;
inline string better(string a,string b)
{
if(a=="")
return b;
if(a.size()!=b.size())
return a.size() q;
for(int i=0;i