vjudge

Description

For the hope of a forever love, Steven is planning to send a ring to Jane with a romantic string engraved on. The string's length should not exceed N. The careful Steven knows Jane so deeply that he knows her favorite words, such as "love", "forever". Also, he knows the value of each word. The higher value a word has the more joy Jane will get when see it.

The weight of a word is defined as its appeared times in the romantic string multiply by its value, while the weight of the romantic string is defined as the sum of all words' weight. You should output the string making its weight maximal.

Input

The input consists of several test cases. The first line of input consists of an integer T, indicating the number of test cases. Each test case starts with a line consisting of two integers: N, M, indicating the string's length and the number of Jane's favorite words. Each of the following M lines consists of a favorite word Si. The last line of each test case consists of M integers, while the i-th number indicates the value of Si.

Technical Specification

1. T ≤ 15
2. 0 < N ≤ 50, 0 < M ≤ 100.
3. The length of each word is less than 11 and bigger than 0.
4. 1 ≤ Hi ≤ 100.
5. All the words in the input are different.
6. All the words just consist of 'a' - 'z'.

Output

For each test case, output the string to engrave on a single line.

If there's more than one possible answer, first output the shortest one. If there are still multiple solutions, output the smallest in lexicographically order.

The answer may be an empty string.

Sample Input

2
7 2
love
ever
5 5
5 1
ab
5

Sample Output

lovever
abab

简单翻译一下:给出m个模式串(m≤100),每个模式串有一个权值。先要求构造一个长度不大于n(n≤50)的串使其包含的子模式串的权值和最大。若存在多解,则要求输出长度最小的,若仍存在多解则要求输出字典序最小的。

sol

DP出最大权值应该不难吧

要求字典序最小其实也很好办。开一个string记录路径就行了(string自带比较字典序)。

code

#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
using namespace std;
const int N = 1500;
int T,n,m,tot,ch[26][N],fail[N],cnt[N],node[101],dp[55][N];
string path[55][N];
char s[N];
queue<int>Q;
void Insert(int k)
{
cin>>s;int l=strlen(s),x=0;
for (int i=0;i<l;i++)
{
if (!ch[s[i]-'a'][x]) ch[s[i]-'a'][x]=++tot;
x=ch[s[i]-'a'][x];
}
node[k]=x;
}
void Get_Fail()
{
for (int i=0;i<26;i++) if (ch[i][0]) Q.push(ch[i][0]);
while (!Q.empty())
{
int u=Q.front();Q.pop();
for (int i=0;i<26;i++)
if (ch[i][u]) fail[ch[i][u]]=ch[i][fail[u]],Q.push(ch[i][u]);
else ch[i][u]=ch[i][fail[u]];
cnt[u]+=cnt[fail[u]];
}
}
void DP()
{
memset(dp,-1,sizeof(dp));
dp[0][0]=0;path[0][0]="";
for (int i=0;i<n;i++)
for (int j=0;j<=tot;j++)
if (dp[i][j]!=-1)
for (int k=0;k<26;k++)
{
int u=ch[k][j];
if (dp[i][j]+cnt[u]>dp[i+1][u])
{
dp[i+1][u]=dp[i][j]+cnt[u];
path[i+1][u]=path[i][j]+(char)(k+'a');
}
else if (dp[i][j]+cnt[u]==dp[i+1][u])
{
string str=path[i][j]+(char)(k+'a');
if (str<path[i+1][u]) path[i+1][u]=str;
}
}
}
int main()
{
cin>>T;
while (T--)
{
cin>>n>>m;
for (int i=0;i<=tot;i++)
{
fail[i]=cnt[i]=0;
for (int j=0;j<26;j++) ch[j][i]=0;
}
tot=0;
for (int i=1;i<=m;i++) Insert(i);
for (int i=1,v;i<=m;i++) cin>>v,cnt[node[i]]+=v;
Get_Fail();
DP();
string str="";int ans=0,maxx=0;
for (int i=1;i<=n;i++)
for (int j=0;j<=tot;j++)
maxx=max(maxx,dp[i][j]);
for (int i=1;i<=n;i++)
{
for (int j=0;j<=tot;j++)
if (dp[i][j]>ans||(dp[i][j]==ans&&path[i][j]<str))
ans=dp[i][j],str=path[i][j];
if (ans==maxx) break;
}
cout<<str<<endl;
}
return 0;
}

[HDU2296]Ring的更多相关文章

  1. HDU2296 Ring —— AC自动机 + DP

    题目链接:https://vjudge.net/problem/HDU-2296 Ring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit ...

  2. 【AC自动机】【动态规划】hdu2296 Ring

    题解:http://www.cnblogs.com/swm8023/archive/2012/08/08/2627535.html 要输出路径,价值最大优先,价值相同的取长度较小者,仍相同取字典序较小 ...

  3. HDU-2296 Ring(AC自动机+DP)

    题目大意:给出的m个字符串都有一个权值.用小写字母构造一个长度不超过n的字符串S,如果S包含子串s,则S获取s的权值.输出具有最大权值的最小字符串S. 题目分析:先建立AC自动机.定义状态dp(ste ...

  4. HDU2296 Ring(AC自动机 DP)

    dp[i][j]表示行走i步到达j的最大值,dps[i][j]表示对应的串 状态转移方程如下: dp[i][chi[j][k]] = min(dp[i - 1][j] + sum[chi[j][k]] ...

  5. HDU2296 Ring(AC自动机+DP)

    题目是给几个带有价值的单词.而一个字符串的价值是 各单词在它里面出现次数*单词价值 的和,问长度不超过n的最大价值的字符串是什么? 依然是入门的AC自动机+DP题..不一样的是这题要输出具体方案,加个 ...

  6. HDU2296——Ring(AC自动机+DP)

    题意:输入N代表字符串长度,输入M代表喜欢的词语的个数,接下来是M个词语,然后是M个词语每个的价值.求字符串的最大价值.每个单词的价值就是单价*出现次数.单词可以重叠.如果不止一个答案,选择字典序最小 ...

  7. AC自动机基础知识讲解

    AC自动机 转载自:小白 还可参考:飘过的小牛 1.KMP算法: a. 传统字符串的匹配和KMP: 对于字符串S = ”abcabcabdabba”,T = ”abcabd”,如果用T去匹配S下划线部 ...

  8. AC自动机题单

    AC自动机题目 真的超级感谢xzy 真的帮到我很多 题单 [X] [luogu3808][模板]AC自动机(简单版) https://www.luogu.org/problemnew/show/P38 ...

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

    Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submissio ...

随机推荐

  1. 克隆虚拟机以及两台linux机器相互登录:linux学习第四篇

    克隆虚拟机 1.      克隆 之后自己命名克隆的虚拟机并自己选择存放位置,完成克隆 2.      克隆虚拟机之后对新的虚拟机修改网络配置,以免冲突(将配置文件里的UUID去掉,并修改IP地址) ...

  2. PHPUnit-附录 C. XML 配置文件

    [http://www.phpunit.cn/manual/5.7/zh_cn/appendixes.configuration.html] PHPUnit <phpunit> 元素的属性 ...

  3. python学习:99乘法口诀

    #!/usr/bin/python   for i in xrange(1,10):     for j in xrange(1,i+1):         print "%s*%s=%s& ...

  4. 【Unity3D技术文档翻译】第1.6篇 使用 AssetBundle Manager

    上一章:[Unity3D技术文档翻译]第1.5篇 使用 AssetBundles 本章原文所在章节:[Unity Manual]→[Working in Unity]→[Advanced Develo ...

  5. 如何写出测不出bug的测试用例

    我们写测试用例的目的是为了能够整理思路,把要测试的地方列出来,做为知识的积淀,用例可以交给其他测试人员执行,或者是跟需求提出者进行讨论,对用例进行补充和修改. 理论上用例写的越多,越容易发现bug.但 ...

  6. PHP秒杀系统全方位设计(一)

    秒杀系统特点人多商品少时间短流量高外挂机器[黄牛和非黄牛] 技术分析瞬间高并发的处理能力多层次的分布式处理能力人机交互与对抗[12306验证码图片] 技术选型分析Linux+Nginx+PHP+Mys ...

  7. hdu 1207 四柱汉诺塔

    递推,汉诺塔I的变形. 这题真心没想到正确解法,越想越迷糊.这题看了别人题解过得,以后还是自己多想想,脚步太快并非好事. 贴上分析:   分析:设F[n]为所求的最小步数,显然,当n=1时,F[n]= ...

  8. hdu 2553 N皇后

    这题要打表,不然超时. AC代码 #include<cstdio> #include<cstring> int n,cnt; int vis[3][20]; int ans[1 ...

  9. 吾八哥学Selenium(三):操作复选框checkbox/单选框radio的方法

    复选框checkbox和单选框radio是web网站里经常会使用到的两个控件,那么在web自动化测试的时候如何利用Selenium来操作这俩控件呢?今天我们就来简单入门练习一下! html测试页面代码 ...

  10. Unix代码段和数据段

    关于UNIX系统代码段和数据段分开的目的:方便编程. 1)代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像.代码段需要防止在运行时被非法修改,所以只准许读取操作,而 ...