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)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. hdu 2296 aC自动机+dp(得到价值最大的字符串)

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

  7. 对AC自动机+DP题的一些汇总与一丝总结 (2)

    POJ 2778 DNA Sequence (1)题意 : 给出m个病毒串,问你由ATGC构成的长度为 n 且不包含这些病毒串的个数有多少个 关键字眼:不包含,个数,长度 DP[i][j] : 表示长 ...

  8. POJ1625 Censored!(AC自动机+DP)

    题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...

  9. HDU2457 DNA repair(AC自动机+DP)

    题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步) ...

随机推荐

  1. Apache Thrift 环境配置

    在 Ubuntu 14.04 下Apache Thrift 的安装方法: 1安装依赖包 sudo apt-get install libboost-dev libboost-test-dev libb ...

  2. linux文件远程传输客户端shell脚本与分布式客户机时间同步脚本

    #!/bin/bash # 将代码和脚本传送至worker节点 # 改变当前工作目录 cd ${AMAZONCRAWLER_HOME} #读取worker节点ip列表 i= while read li ...

  3. java抓取快递信息

    package zeze; import java.io.IOException; import org.jsoup.Connection; import org.jsoup.Jsoup; impor ...

  4. idea java 正则表达式匹配替换

    原文匹配中文 excelMap.get\((\"[\u4E00-\u9F15]+\")\) 目标 excelMap.get\($1.hashCode\(\)\)

  5. oracle数据库高级应用之《触发器的建立》

    (一)oracle数据库触发器的建立 eg1 CREATE OR REPLACE TRIGGER TRIGGER_ON_TD_DEPARTMENT AFTER INSERT OR UPDATE OR ...

  6. Print Common Nodes in Two Binary Search Trees

    Given two Binary Search Trees, find common nodes in them. In other words, find intersection of two B ...

  7. 页面加载时执行JQ代码

    $(function () { //jq加载时执行的这里面是 $("#ss").append("<strong>这是新加的</strong>&qu ...

  8. poj 1442

    一个排序的题目. 题意:给你m个数a[m],和n个数b[n]. 首先a[0]….a[b[0]]排序.输出第一个数. 然后a[0]….a[b[1]]排序.输出第二个数. 以此类推,直到输出第n个数. 思 ...

  9. struts2类型转换器、 类型转换错误 以及INPUT view

    1.1.1    Struts2中的类型转换器 Struts2内置了常见数据类型多种转换器 boolean 和 Boolean char和 Character int 和 Integer long 和 ...

  10. CEF3开发者系列之JS与C++交互之一

    JS与Native交互是相对于比较困难的技术,在学习这门技术之前,我们先了解下浏览器内核中的JS引擎与chromium内核的V8引擎相关知识.在浏览器应用中,JS与本地代码互相调用,得益于浏览器内核对 ...