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步) ...
随机推荐
- SNMP常用数据操作
SNMP常用数据操作 snmp编程中常见的数据类型基本上就是integer32/oct_str(字节数组)/counter64/timeticks/dateAndTime这些.很多其它的比如Truth ...
- C/C++相对论——C++中为什么要使用异常?
C++中为什么要使用异常? 很多人也许知道C++中的异常机制,很多人也许不知道.很多人知道C中常用的assert,也知道在编译时候指定NODEBUG来忽略它. 对于C语言,使用正常的if-else即是 ...
- 服务器设置SSH 长连接
1.echo $TMOUT 如果显示空白,表示没有设置, 等于使用默认值0, 一般情况下应该是不超时. 如果大于0, 可以在如/etc/profile之类文件中设置它为0. 2.修改/etc/ssh/ ...
- 5.3(2)----机器人走方格2(CC150)
这道题只需要把障碍点都设为0就可以了. public static int countWays(int[][] map,int x, int y){ if( x < 0 || y < 0) ...
- Yii中的错误及异常处理
Yii中的错误及异常处理 Yii已经默认已经在CApplication上实现了异常和错误的接管,这是通过php的set_exception_handler, set_error_handler实现的. ...
- python to be linux daemon
所需第三方库:python-daemon[https://pypi.python.org/pypi/python-daemon/] 使用方式: python linux_service.py star ...
- Java for LeetCode 224 Basic Calculator
Implement a basic calculator to evaluate a simple expression string. The expression string may conta ...
- Java for LeetCode 217 Contains Duplicate
Given an array of integers, find if the array contains any duplicates. Your function should return t ...
- linux 解压缩
tar f 使用档案名字,这个参数是最后一个参数,后面只能接档案名 c 建立压缩档案 x 解压 t 查看内容 r 向压缩归档文件末尾追加文件 u 更新原压缩包中的文件 z 有gzip属性的 j 有bz ...
- js的json转换
静态页面是: data:[{ value:2.5, itemStyle:{ normal:{color:'#4a90e2'} } },{ value:2.5, itemStyle:{ normal:{ ...