HDU 2296 Ring ( Trie图 && DP && DP状态记录)
题意 : 给出 m 个单词,每一个单词有一个权重,如果一个字符串包含了这些单词,那么意味着这个字符串拥有了其权重,问你构成长度为 n 且权重最大的字符串是什么 ( 若有权重相同的,则输出最短且字典序最小的 )
分析 : 如果你做过 POJ 2778 或者 HDU 2243 以及诸如此类的题目,那么这道题的难点就不在构建 Trie图上了,没有接触过Trie图的建议先了解,下面进入正题。这道题相对于普通的 AC自动机orTrie图 + DP 的题目而言,共同点是都是利用 Trie图进行状态的转移,现在增加了权重以及要求输出具体的字符串答案。我们定义 DP[i][j] 为构建了长度为 i 且最后一个字符为 j 的字符串最大权重,由于每一个状态都对应一个字符串,所以再构建一个三维字符数组 s[i][j][k] 表示当前 i、j 状态下具体的字符串为 s[i][j][0~k-1],那么状态转移方程就是
DP[i+1][ Trie[j][k] ] = max( DP[i+1][ Trie[j][k] ] , DP[i][j] + Trie[j][k].val )
( Trie[j][k] 代表 j 状态可以一步转移到 k状态,如果你做过类似题目,那你不会陌生)
在状态转移的时候需要时时更新 s[i][j][k] 这个三维数组,当取得更优值的时候需要更新,最后只要在DP的过程当中记录最优的权重、状态i、j下标然后DP结束后输出即可。当然有个小优化,这种DP属于向前的DP,如果当前DP值是你设置的初值,那么它是没意义的,可以直接continue,因为它不会对后面的DP值产生影响。
#include<string.h>
#include<stdio.h>
#include<queue>
using namespace std;
;
;
][];
][][];///存储每一个状态所代表的具体字符串
struct Aho{
struct StateTable{
int Next[Letter];
int fail, val;
}Node[Max_Tot];
int Size;
queue<int> que;
inline void init(){
while(!que.empty()) que.pop();
memset(Node[].Next, , ].Next));
Node[].fail = Node[].val = ;
Size = ;
}
inline void insert(char *s, int val){
;
; s[i]; i++){
int idx = s[i] - 'a';
if(!Node[now].Next[idx]){
memset(Node[Size].Next, , sizeof(Node[Size].Next));
Node[Size].fail = Node[Size].val = ;
Node[now].Next[idx] = Size++;
}
now = Node[now].Next[idx];
}
Node[now].val = val;
}
inline void BuildFail(){
Node[].fail = ;
; i<Letter; i++){
].Next[i]){
Node[Node[].Next[i]].fail = ;
que.push(Node[].Next[i]);
}].Next[i] = ;
}
while(!que.empty()){
int top = que.front(); que.pop();
Node[top].val += Node[Node[top].fail].val;///这里需要注意!
; i<Letter; i++){
int &v = Node[top].Next[i];
if(v){
que.push(v);
Node[v].fail = Node[Node[top].fail].Next[i];
}else v = Node[Node[top].fail].Next[i];
}
}
}
}ac;
][];
int main(void)
{
int nCase;
scanf("%d", &nCase);
while(nCase--){
int n, m;
scanf("%d %d", &n, &m);
; i<m; i++)
scanf("%s", tmp[i]);
int tmpVal;
ac.init();
; i<m; i++){
scanf("%d", &tmpVal);
ac.insert(tmp[i], tmpVal);
}
ac.BuildFail();
; i<=n; i++){///将所有DP的值赋为 -1
; j<ac.Size; j++){
dp[i][j] = -;
s[i][j][] = '\0';
}
}
dp[][] = ;///定义初始状态
];
int ii, jj, MaxSum;
ii = jj = MaxSum = ;
; i<n; i++){
; j<ac.Size; j++){
){///如果当前dp值不是初始状态则进入if,否则其dp值毫无意义,直接跳过
; k>=; k--){///一开始我是想谋求字典序最小而从后往前,但是WA一发后我发现我错了,实际上顺序不重要
;
int newj = ac.Node[j].Next[k];
int sum = dp[i][j] + ac.Node[ newj ].val;
if(sum > dp[newi][newj]){
dp[newi][newj] = sum;
strcpy(s[newi][newj], s[i][j]);
int len = strlen(s[i][j]);
s[newi][newj][len] = k+'a';
s[newi][newj][len+] = '\0';
}else if(sum == dp[newi][newj]){///谋求字典序最小应该实在dp值相等情况下
strcpy(str, s[i][j]);
int len = strlen(str);
str[len] = 'a'+k;
str[len+] = '\0';
)
strcpy(s[newi][newj], str);
}
if(dp[newi][newj] >= MaxSum){///更新一下最终的答案
if(dp[newi][newj] == MaxSum){
int L1 = strlen(s[newi][newj]);
int L2 = strlen(s[ii][jj]);
)
ii = newi, jj = newj;
}else{
MaxSum = dp[newi][newj];
ii = newi, jj = newj;
}
}
}
}
}
}
) puts("");///如果最后权值依旧是 0 那么输出空串
else puts(s[ii][jj]);
}
;
}
HDU 2296 Ring ( Trie图 && DP && DP状态记录)的更多相关文章
- HDU 2296 Ring (AC自动机+DP)
Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- HDU 2296 Ring [AC自动机 DP 打印方案]
Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submissio ...
- BZOJ3530: [Sdoi2014]数数(Trie图,数位Dp)
Description 我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串.例如当S=(22,333,0233)时,233是幸运数,2333.20233.3 ...
- HDU 2296:Ring
Problem Description For the hope of a forever love, Steven is planning to send a ring to Jane with a ...
- HDU 2296 Ring -----------AC自动机,其实我想说的是怎么快速打印字典序最小的路径
大冥神的代码,以后能贴的机会估计就更少了....所以本着有就贴的好习惯,= =....直接贴 #include <bits/stdc++.h> using LL = long long ; ...
- HDU 4511 小明系列故事——女友的考验 ( Trie图 && DP )
题意 : 给出编号从1 ~ n 的 n 个平面直角坐标系上的点,求从给出的第一个点出发到达最后一个点的最短路径,其中有两种限制,其一就是只能从编号小的点到达编号大的点,再者不能走接下来给出的 m 个 ...
- HDU 4057 Rescue the Rabbit ( AC自动机 + 状态压缩DP )
模板来自notonlysuccess. 模式串只有10个,并且重复出现的分值不累加,因此很容易想到状态压缩. 将模式串加入AC自动机,最多有10*100个状态. dp[i][j][k]:串长为i,在T ...
- POJ 1625 Censored ( Trie图 && DP && 高精度 )
题意 : 给出 n 个单词组成的字符集 以及 p 个非法串,问你用字符集里面的单词构造长度为 m 的单词的方案数有多少种? 分析 :先构造出 Trie 图方便进行状态转移,这与在 POJ 2278 中 ...
- HDU 3341 Lost's revenge ( Trie图 && 状压DP && 数量限制类型 )
题意 : 给出 n 个模式串,最后给出一个主串,问你主串打乱重组的情况下,最多能够包含多少个模式串. 分析 : 如果你做过类似 Trie图 || AC自动机 + DP 类似的题目的话,那么这道题相对之 ...
随机推荐
- Web测试常用的链接测试工具
1.Xenu Link Sleuth 详细解说地址:http://home.snafu.de/tilman/xenulink.htm http://pan.baidu.com/s/1qY3Tp4C(英 ...
- Hive-生成一个大文件(小文件合并)
set hive.execution.engine=mr; --在 map-reduce 作业结束时合并小文件.如启用,将创建 map-only 作业以合并目标表/分区中的文件. set hive.m ...
- 选择排序--python
def findSmallest(arr): smallest = arr[0] smallest_index = 0 for i in range(1, len(arr)): if arr[i] & ...
- @-webkit-keyframes 动画 css3
Internet Explorer 10.Firefox 以及 Opera 支持 @keyframes 规则和 animation 属性. Chrome 和 Safari 需要前缀 -webkit-. ...
- P1540翻译机器
这是2010提高组第一题,是一个使用队列的模拟题(然而洛谷很多大佬用了最短路) 这道题首先要判断内存中是否已有解释(因为题目已经说了长度很小,所以可以用桶排序),没有的话便去外存找,找到后,存到内存的 ...
- 区间gcd
http://codeforces.com/problemset/problem/914/D 题意:给你n个数,两种操作:1.询问区间[l,r]在至多一次修改一个数的条件下区间gcd是否等于x. 2. ...
- 题解 AT1357 【n^p mod m】
此题就是快速幂取模 先简单讲一讲快速幂 首先,快速幂的目的就是做到快速求幂,假设我们要求a^b,按照朴素算法就是把a连乘b次,这样一来时间复杂度是O(b)也即是O(n)级别,快速幂能做到O(logn) ...
- Ubuntu 解决wifi无法打开的问题 安装NVIDIA显卡驱动的正确姿势
游戏本型号Y7000 win10 Ubuntu16.04双系统 解决wifi无法打开的问题 解决方法: 1.打开终端输入:rfkill list all 出现如下提示:: 可以看到,优先级 ...
- 05: zabbix 监控配置
目录:zabbix其他篇 01: 安装zabbix server 02:zabbix-agent安装配置 及 web界面管理 03: zabbix API接口 对 主机.主机组.模板.应用集.监控项. ...
- Android真机测试时无法连接服务器
之前服务器的通信一直是在模拟机上实现的,今天用在真机上却不成功.百度之后发现是安卓9以后禁止使用HTTP直接访问服务器.记录一下以后使用. 参考博文:https://blog.csdn.net/don ...