HDU-2296 Ring(AC自动机+DP)
题目大意:给出的m个字符串都有一个权值。用小写字母构造一个长度不超过n的字符串S,如果S包含子串s,则S获取s的权值。输出具有最大权值的最小字符串S。
题目分析:先建立AC自动机。定义状态dp(step,u)表示长度为step、在u节点上的最大权值。状态转移方程为:dp(step,u)=max(dp(step-1,v)+w(u))。其中,v为能到达u的前一个节点。
代码如下:
# include<iostream>
# include<cstdio>
# include<queue>
# include<string>
# include<cstring>
# include<algorithm>
using namespace std; int cnt;
int ch[1200][26];
int fail[1200];
int val[1200];
int w[105]; void init()
{
cnt=0;
memset(ch,-1,sizeof(ch));
memset(val,0,sizeof(val));
} int idx(char c)
{
return c-'a';
} void insert(char *s,int key)
{
int len=strlen(s);
int r=0;
for(int i=0;i<len;++i){
int c=idx(s[i]);
if(ch[r][c]==-1) ch[r][c]=++cnt;
r=ch[r][c];
}
val[r]=w[key];
} void getFail()
{
queue<int>q;
fail[0]=0;
for(int i=0;i<26;++i){
if(ch[0][i]==-1)
ch[0][i]=0;
else{
fail[ch[0][i]]=0;
q.push(ch[0][i]);
}
}
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=0;i<26;++i){
if(ch[u][i]==-1)
ch[u][i]=ch[fail[u]][i];
else{
fail[ch[u][i]]=ch[fail[u]][i];
q.push(ch[u][i]);
}
}
}
} char h[105][15];
int dp[55][1200];
string path[55][1200]; bool isSmall(string s,string t)
{
if(t=="") return true;
if(s.size()<t.size()) return true;
if(s.size()>t.size()) return false;
return s<t;
} string DP(int n)
{
memset(dp,-1,sizeof(dp));
dp[0][0]=0;
for(int i=0;i<=n;++i) for(int j=0;j<=cnt;++j)
path[i][j]="";
int fen=0;
for(int i=0;i<=n;++i){
for(int j=0;j<=cnt;++j){
if(dp[i][j]==-1) continue;
for(int c=0;c<26;++c){
if(dp[i+1][ch[j][c]]<dp[i][j]+val[ch[j][c]]){
dp[i+1][ch[j][c]]=dp[i][j]+val[ch[j][c]];
path[i+1][ch[j][c]]=path[i][j]+(char)('a'+c);
}else if(dp[i+1][ch[j][c]]==dp[i][j]+val[ch[j][c]]){
if(isSmall(path[i][j]+(char)('a'+c),path[i+1][ch[j][c]]))
path[i+1][ch[j][c]]=path[i][j]+(char)('a'+c);
}
}
if(i>0) fen=max(fen,dp[i][j]);
}
}
if(fen==0) return "";
string res="";
for(int i=1;i<=n;++i) for(int j=0;j<=cnt;++j){
if(dp[i][j]==fen&&isSmall(path[i][j],res)){
res=path[i][j];
}
}
return res;
} int main()
{
int T,n,m;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d%d",&n,&m);
for(int i=0;i<m;++i)
scanf("%s",h[i]);
w[0]=0;
for(int i=1;i<=m;++i)
scanf("%d",w+i);
for(int i=0;i<m;++i)
insert(h[i],i+1);
getFail();
cout<<DP(n)<<endl;
}
return 0;
}
HDU-2296 Ring(AC自动机+DP)的更多相关文章
- HDU 2296 Ring [AC自动机 DP 打印方案]
Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submissio ...
- HDU 2296 Ring -----------AC自动机,其实我想说的是怎么快速打印字典序最小的路径
大冥神的代码,以后能贴的机会估计就更少了....所以本着有就贴的好习惯,= =....直接贴 #include <bits/stdc++.h> using LL = long long ; ...
- HDU2296 Ring —— AC自动机 + DP
题目链接:https://vjudge.net/problem/HDU-2296 Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit ...
- HDU 2296 Ring ( Trie图 && DP && DP状态记录)
题意 : 给出 m 个单词,每一个单词有一个权重,如果一个字符串包含了这些单词,那么意味着这个字符串拥有了其权重,问你构成长度为 n 且权重最大的字符串是什么 ( 若有权重相同的,则输出最短且字典序最 ...
- 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]] ...
- 对AC自动机+DP题的一些汇总与一丝总结 (2)
POJ 2778 DNA Sequence (1)题意 : 给出m个病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个 关键字眼:不包含,个数,长度 DP[i][j] : 表示长 ...
- hdu 2296 aC自动机+dp(得到价值最大的字符串)
Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- HDU 2425 DNA repair (AC自动机+DP)
DNA repair Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- HDU 3341 Lost's revenge AC自动机+dp
Lost's revenge Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)T ...
随机推荐
- Linux编程 ---- dup函数
dup,dup2,dup3函数 顾名思义,dup及duplicate的简写,也就是复制的意思.而事实上这几个函数的功能也确实是复制文件描述符.那为什么要复制文件描述符呢?呵呵,我认为是程序 ...
- 作业8 Alpha阶段项目总结
我们的扫雷游戏已经基本完成. 游戏共分3个难度 每个难度的格数和雷的格数也有不同 具体的游戏会在展示时候让大家看到 小组成员分数: 史劭聪 20分 马浩然 20分
- C# 学习电子书资料分享mobi epub等格式
.NET之美:.NET关键技术深入解析 作者: 张子阳 出版社:机械工业出版社 大小:20.29MB 出版时间:14-01-01 格式:mobi ASP.NET 4权威指南 作者: 马伟 出版社: 大 ...
- PyAutoGUI-python版的autoit/AHK
简单介绍各个图形界面自动操作的python库,类似按键精灵\autoit\ahk(autohotkey)等等这些自动化工具.这类python库不是只是用来实现自动游戏之类的程序,业界也用这些库来做GU ...
- android studio 2.2.2下fragment的创建和跳转
一,首先,Fragment是android应用中十分重要的一个功能,十分轻量化,也类似于activity一样,是一个个布局,可以相互跳转和传递参数.但是,它运行起来十分流畅,而且易于管理,下面是在学习 ...
- NSIS 让程序以管理权限运行
用NSIS向导,制作安装包,会生成NSI扩展的脚本文件,按F9,即可以生成安装文件. 如果要以管理员权限运行,直接在nsi脚本中,添加RequestExecutionLevel admin Name ...
- redis基础总结
Redis 数据类型: String Hash String类型: 一个key对应一个value,二进制安全的. set方法:设置对应值的value set name value get方法:获取对应 ...
- linux命令:chmod
1.命令介绍: chmod用来改变系统文件或目录的相关权限,可读,可写,可执行等. 2.命令格式: chmod [选项] 模式 文件 3.命令参数: 必要参数:-c 当发生改变时,报告处理信息-f 错 ...
- IDEA 的 git 使用
push的时候出现"push rejected": 1)先fetch: 2)然后选择branches--origin/master---rebaseOnto 3)再进行push,刚 ...
- JS简介
JS是一本广泛应用于浏览器客户端的脚本语言,由netspace公司设计,当时和sun公司合作,所以名字取得像java JS的常见用途:1)HTML DOM操作(节点操作,比如添加.修改.删除节点 ) ...