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. WPF项目学习.三

    工具代码记录 版权声明:本文为博主初学经验,未经博主允许不得转载. 一.前言 记录在学习与制作WPF过程中遇到的解决方案. 分页控件的制作,邮件发送,日志代码,excel导入导出等代码的实现过程: 二 ...

  2. PHP中cookies跨目录无法调用解决办法

    localhost/a/test.php 中写入: <?php setcookie("user","zhangsan",time()+3600); ?&g ...

  3. GitHub中开启二次验证Two-factor authentication,如何在命令行下更新和上传代码

    最近在使用GitHub管理代码,在git命令行管理代码时候遇到一些问题.如果开起了二次验证(Two-factor authentication两个要素认证),命令行会一直提示输入用户名和密码.查找了一 ...

  4. mac 查看某个文件夹下所有隐藏文件(夹)的大小

    du -d 1 -h 对应Linux的命令是: du -ah --max-depth=1

  5. iptables snat和dnat

    iptables中的snat和dnat是非常有用的,感觉他们二个比较特别,所以单独拿出来说一下. dnat是用来做目的网络地址转换的,就是重写包的目的IP地址.如果一个包被匹配了,那么和它属于同一个流 ...

  6. CentOS7中关闭firewall,并使用iptables管理防火墙

    背景描述 在使用Docker时,启用centos7默认的firewall,启动端口映射时,防火墙规则不生效.docker默认使用了iptables防火墙机制.所以需要关闭firewall使用iptab ...

  7. 【mysql】 操作 收集持续更新

    一个字段可能对应多条数据,用mysql实现将多行数据合并成一行数据 GROUP_CONCAT(Name SEPARATOR ',') 需注意: 1.GROUP_CONCAT()中的值为你要合并的数据的 ...

  8. Spring-Security自定义登录页&inMemoryAuthentication验证

    Spring Security是为基于Spring的应用程序提供声明式安全保护的安全性框架.框架下内容比较多,可以做到按照角色权限对请求路径进行限制.今天主要验证自定义登录页,在内存用户存储中进行请求 ...

  9. $.ajax的一些坑啊

    1.如果发送ajax返回的数据为json务必设置其 Content-Type:application/json;charset=UTF-8 不然会导致其success:function(data)中的 ...

  10. 上帝之眼APP——实时定位监控、即时通讯

    项目地址 https://github.com/guoyaohua/GodsEYE 开发环境 Android studio 2.3.1 极光推送IM SDK 百度鹰眼SDK 背景介绍 定位监控系统,不 ...