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]])
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<string>
#include<queue>
using namespace std; #define hash(x) x-'a';
const int N = 20000, CH = 26, INF = 0x3F3F3F3F;
int n, m;
struct Trie{
Trie *next[CH];
Trie *fail;
int id;
}tree[N];
string dps[60][2008];
string ans; //dp[i][j]表示行走i步到达j的最大值,dps[i][j]表示对应的串
int dp[60][2008];
int chi[1008][CH];
int sum[1008]; //先选长度短的,再按字典序选
inline string min(string &a, string &b){
if(a.size() != b.size()){
return a.size() < b.size()? a :b;
}
return a < b? a :b;
}
class AC_Auto{
int size;
Trie *root;
int mx; public:
AC_Auto(){
root = &tree[0];
size=0;
memset(&tree[0], 0, sizeof(Trie));
} void insert(char *s, int si){
Trie *p = root;
for(int i = 0; s[i]; i++){
int c = hash(s[i]);
if(!p -> next[c]){
memset(&tree[++size], 0, sizeof(Trie));
p -> next[c] = &tree[size];
p -> next[c] ->id = size;
}
p = p -> next[c];
}
sum[p -> id] = si;
} void build(){
queue<Trie *> q;
q.push(root);
root -> fail = NULL;
while(!q.empty()){
Trie *now = q.front();
q.pop();
if(now -> fail){
//累加求串包含的子串价值和
sum[now -> id] += sum[now -> fail -> id];
}
for(int i = 0; i < CH; i++){
Trie *son = now -> next[i];
Trie *tp = (now == root)? root: now -> fail->next[i];
if(son == NULL){
now -> next[i] = tp;
}else{
son -> fail = tp;
q.push(son);
}
son = now -> next[i];
chi[now -> id][i] = son->id;
}
}
}
void solve(){
mx = 0;
ans.clear();
for(int i = 0; i <= n; i++){
for(int j = 0; j <= size; j++){
dp[i][j] = -INF;
dps[i][j].clear();
}
}
dp[0][0] = 0;
//枚举步骤,再枚举节点,状态转移
for(int i = 1; i <= n; i++){
for(int j = 0; j <= size; j++){
if(dp[i - 1][j] < 0){
continue;
}
for(int k = 0; k < CH; k++){
if(dp[i][chi[j][k]] < dp[i - 1][j] + sum[chi[j][k]]){
dp[i][chi[j][k]] = dp[i - 1][j] + sum[chi[j][k]]; dps[i][chi[j][k]] = dps[i - 1][j] + (char)(k + 'a'); }else if(dp[i][chi[j][k]] == dp[i - 1][j] + sum[chi[j][k]]){
dps[i][chi[j][k]] = min(dps[i - 1][j] + (char)(k + 'a'), dps[i][chi[j][k]]);
} if(mx < dp[i][chi[j][k]]){
mx = dp[i][chi[j][k]];
ans = dps[i][chi[j][k]];
}else if(mx == dp[i][chi[j][k]]){
ans = min(ans, dps[i][chi[j][k]]);
}
}
} }
if(ans.size() > 0){
cout<<ans<<"\n";
}else{ cout<<"\n";
} }
}; char str[1008][1008];
int main(){
int t;
cin>>t;
while(t--){
AC_Auto ac;
cin>>n>>m;
memset(sum, 0 , sizeof(sum)); for(int i = 0; i < m; i++){
scanf("%s", str[i]);
}
for(int i = 0; i < m ; i++){
int val;
scanf("%d", &val);
ac.insert(str[i], val);
}
ac.build();
ac.solve();
}
return 0;
}
HDU2296 Ring(AC自动机 DP)的更多相关文章
- HDU2296 Ring —— AC自动机 + DP
题目链接:https://vjudge.net/problem/HDU-2296 Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit ...
- HDU-2296 Ring(AC自动机+DP)
题目大意:给出的m个字符串都有一个权值.用小写字母构造一个长度不超过n的字符串S,如果S包含子串s,则S获取s的权值.输出具有最大权值的最小字符串S. 题目分析:先建立AC自动机.定义状态dp(ste ...
- HDU 2296 Ring [AC自动机 DP 打印方案]
Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submissio ...
- HDU2296 Ring(AC自动机+DP)
题目是给几个带有价值的单词.而一个字符串的价值是 各单词在它里面出现次数*单词价值 的和,问长度不超过n的最大价值的字符串是什么? 依然是入门的AC自动机+DP题..不一样的是这题要输出具体方案,加个 ...
- HDU2296——Ring(AC自动机+DP)
题意:输入N代表字符串长度,输入M代表喜欢的词语的个数,接下来是M个词语,然后是M个词语每个的价值.求字符串的最大价值.每个单词的价值就是单价*出现次数.单词可以重叠.如果不止一个答案,选择字典序最小 ...
- hdu 2296 aC自动机+dp(得到价值最大的字符串)
Ring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 对AC自动机+DP题的一些汇总与一丝总结 (2)
POJ 2778 DNA Sequence (1)题意 : 给出m个病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个 关键字眼:不包含,个数,长度 DP[i][j] : 表示长 ...
- POJ1625 Censored!(AC自动机+DP)
题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...
- HDU2457 DNA repair(AC自动机+DP)
题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步) ...
随机推荐
- Http Request
function getSend($url,$param) { $ch = curl_init($url."?".$param); curl_setopt($ch,CURLOPT_ ...
- 百度地图API 海量点 自定义添加信息
<!--添加百度地图--> <script type="text/javascript" src="http://api.map.baidu.com/a ...
- TO BE OPEN
我们通常都在一个很狭隘的世界里. 却以为我们有了整个蓝天.
- 【转】【编码】ASCII 、UNICODE和UTF-8之二
字符发展 1. 美国 ASCII-(American standard code information interchange) 美国信息互换标准代码 范围:1-127 ; 单字 备注:前部用作控制 ...
- crontab命令
前一天学习了 at 命令是针对仅运行一次的任务,循环运行的例行性计划任务,linux系统则是由 cron (crond) 这个系统服务来控制的.Linux 系统上面原本就有非常多的计划性工作,因此这个 ...
- JavaScript——正则表达式
1.显式创建正则表达式:var searchPattern=new RegExp(‘+s’);加号会匹配字符串中任何一个带有一个或者多个连续的s. 2.RegExp对象的方法:test和exec te ...
- Find the Duplicate Number
Given an array nums containing n + 1 integers where each integer is between 1 and n (inclusive), pro ...
- strcpy C++实现
#include <iostream> #include <assert.h> using namespace std; char *strcpy(char *strDest, ...
- git diff获取差异文件中文乱码的解决办法
通过git的diff命令对两个commit id的版本进行差异化的对比.中文文件时出现乱码. git diff 6bded8d0c1fe1746c122121217dc0c88667091089 a9 ...
- mysql开启binlog
mysql开启binlog,至于为什么要开启binlog,可以google下. ## 设置server_id,一般设置为IP server_id= ## 复制过滤:需要备份的数据库名,多个库以逗号分隔 ...