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. SNMP常用数据操作

    SNMP常用数据操作 snmp编程中常见的数据类型基本上就是integer32/oct_str(字节数组)/counter64/timeticks/dateAndTime这些.很多其它的比如Truth ...

  2. C/C++相对论——C++中为什么要使用异常?

    C++中为什么要使用异常? 很多人也许知道C++中的异常机制,很多人也许不知道.很多人知道C中常用的assert,也知道在编译时候指定NODEBUG来忽略它. 对于C语言,使用正常的if-else即是 ...

  3. 服务器设置SSH 长连接

    1.echo $TMOUT 如果显示空白,表示没有设置, 等于使用默认值0, 一般情况下应该是不超时. 如果大于0, 可以在如/etc/profile之类文件中设置它为0. 2.修改/etc/ssh/ ...

  4. 5.3(2)----机器人走方格2(CC150)

    这道题只需要把障碍点都设为0就可以了. public static int countWays(int[][] map,int x, int y){ if( x < 0 || y < 0) ...

  5. Yii中的错误及异常处理

    Yii中的错误及异常处理 Yii已经默认已经在CApplication上实现了异常和错误的接管,这是通过php的set_exception_handler, set_error_handler实现的. ...

  6. python to be linux daemon

    所需第三方库:python-daemon[https://pypi.python.org/pypi/python-daemon/] 使用方式: python linux_service.py star ...

  7. Java for LeetCode 224 Basic Calculator

    Implement a basic calculator to evaluate a simple expression string. The expression string may conta ...

  8. Java for LeetCode 217 Contains Duplicate

    Given an array of integers, find if the array contains any duplicates. Your function should return t ...

  9. linux 解压缩

    tar f 使用档案名字,这个参数是最后一个参数,后面只能接档案名 c 建立压缩档案 x 解压 t 查看内容 r 向压缩归档文件末尾追加文件 u 更新原压缩包中的文件 z 有gzip属性的 j 有bz ...

  10. js的json转换

    静态页面是: data:[{ value:2.5, itemStyle:{ normal:{color:'#4a90e2'} } },{ value:2.5, itemStyle:{ normal:{ ...