题意:给你些分数串,给你一个主串,主串每出现一个分数串加一分,要你重新排列主串,最多几分

思路:显然这里开$40^4$去状压内存不够。但是我们自己想想会发现根本不用开那么大,因为很多状态是废状压,不是不存在的,那么可以考虑想办法简化状态。

一个是hash,直接打表所有子情况,用ha[][][][]表示出所有情况,那么直接dp[status][size]去dp。

还有一种用变进制:

假设ACGT的总数分别为num[0],num[1],num[2],num[3]

那么对于ACGT的数量分别为ABCD的状态可以记录为:

A*(num[1]+1)*(num[2]+1)*(num[3]+1) + B*(num[2]+1)*(num[3]+1)+ C*(num[3]+1) +D

显然末尾D基数为1,次末尾C基数(num[3]+1),那么D不管怎么变(最多变num[3])永远影响不到C那个级数((num[3] + 1 )* k),那么就能区分变得是哪一位。

代码:

/*变进制*/
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<string>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 500 + 5;
const int M = 50 + 5;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 20090717;
int n, m;
int dp[15000][maxn];
int getid(char s){if(s == 'A') return 0;if(s == 'C') return 1;if(s == 'G') return 2;return 3;
}
struct Aho{struct state{int next[4];int fail, cnt;}node[maxn];int size;queue<int> q;void init(){size = 0;newtrie();while(!q.empty()) q.pop();}int newtrie(){memset(node[size].next, 0, sizeof(node[size].next));node[size].cnt = node[size].fail = 0;return size++;}void insert(char *s){int len = strlen(s);int now = 0;for(int i = 0; i < len; i++){int c = getid(s[i]);if(node[now].next[c] == 0){node[now].next[c] = newtrie();}now = node[now].next[c];}node[now].cnt++;}void build(){node[0].fail = -1;q.push(0);while(!q.empty()){int u = q.front();q.pop();if(node[node[u].fail].cnt && u) node[u].cnt += node[node[u].fail].cnt;for(int i = 0; i < 4; i++){if(!node[u].next[i]){if(u == 0)node[u].next[i] = 0;elsenode[u].next[i] = node[node[u].fail].next[i];}else{if(u == 0) node[node[u].next[i]].fail = 0;else{int v = node[u].fail;while(v != -1){if(node[v].next[i]){node[node[u].next[i]].fail = node[v].next[i];break;}v = node[v].fail;}if(v == -1) node[node[u].next[i]].fail = 0;}q.push(node[u].next[i]);}}}}void query(char *s){int ans = 0;int len = strlen(s);int num[4] = {0};for(int i = 0; i < len; i++){num[getid(s[i])]++;}memset(dp, -1, sizeof(dp));dp[0][0] = 0;int fac[4];fac[0] = (num[1] + 1) * (num[2] + 1) * (num[3] + 1);fac[1] = (num[2] + 1) * (num[3] + 1);fac[2] = (num[3] + 1);fac[3] = 1;for(int i = 0; i <= num[0]; i++){for(int j = 0; j <= num[1]; j++){for(int k = 0; k <= num[2]; k++){for(int l = 0; l <= num[3]; l++){int id = i * fac[0] + j * fac[1] + k * fac[2] + l;for(int g = 0; g < size; g++){if(dp[id][g] == -1) continue;for(int h = 0; h < 4; h++){int nex;if(h == 0 && i == num[0]) continue;if(h == 1 && j == num[1]) continue;if(h == 2 && k == num[2]) continue;if(h == 3 && l == num[3]) continue;nex = id + fac[h];int add = node[node[g].next[h]].cnt;if(dp[nex][node[g].next[h]] < dp[id][g] + add){dp[nex][node[g].next[h]] = dp[id][g] + add;if(i + j + k + l + 1 == len) ans = max(ans , dp[nex][node[g].next[h]]);}}}}}}}printf("%d\n", ans);}}ac;
char s[45];
int main(){int ca = 1;while(~scanf("%d", &n) && n){ac.init();for(int i = 0; i < n; i++){scanf("%s", s);ac.insert(s);}ac.build();scanf("%s", s);printf("Case %d: ", ca++);ac.query(s);}return 0;
}

/*Hash*/
#include<set>
#include<map>
#include<queue>
#include<cmath>
#include<string>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 500 + 5;
const int M = 50 + 5;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 20090717;
int n, m;
int dp[15000][maxn];
int ha[42][42][42][42];
int getid(char s){if(s == 'A') return 0;if(s == 'C') return 1;if(s == 'G') return 2;return 3;
}
struct Aho{struct state{int next[4];int fail, cnt;}node[maxn];int size;queue<int> q;void init(){size = 0;newtrie();while(!q.empty()) q.pop();}int newtrie(){memset(node[size].next, 0, sizeof(node[size].next));node[size].cnt = node[size].fail = 0;return size++;}void insert(char *s){int len = strlen(s);int now = 0;for(int i = 0; i < len; i++){int c = getid(s[i]);if(node[now].next[c] == 0){node[now].next[c] = newtrie();}now = node[now].next[c];}node[now].cnt++;}void build(){node[0].fail = -1;q.push(0);while(!q.empty()){int u = q.front();q.pop();if(node[node[u].fail].cnt && u) node[u].cnt += node[node[u].fail].cnt;    //attentionfor(int i = 0; i < 4; i++){if(!node[u].next[i]){if(u == 0)node[u].next[i] = 0;elsenode[u].next[i] = node[node[u].fail].next[i];}else{if(u == 0) node[node[u].next[i]].fail = 0;else{int v = node[u].fail;while(v != -1){if(node[v].next[i]){node[node[u].next[i]].fail = node[v].next[i];break;}v = node[v].fail;}if(v == -1) node[node[u].next[i]].fail = 0;}q.push(node[u].next[i]);}}}}void query(char *s){int ans = 0;int len = strlen(s);int tot = 0;int num[4] = {0};for(int i = 0; i < len; i++){num[getid(s[i])]++;}for(int i = 0; i <= num[0]; i++){for(int j = 0; j <= num[1]; j++){for(int k = 0; k <= num[2]; k++){for(int l = 0; l <= num[3]; l++){ha[i][j][k][l] = tot;for(int g = 0; g < size; g++){dp[tot][g] = -1;}tot++;}}}}for(int i = 0; i <= num[0]; i++){for(int j = 0; j <= num[1]; j++){for(int k = 0; k <= num[2]; k++){for(int l = 0; l <= num[3]; l++){}}}}dp[0][0] = 0;for(int i = 0; i <= num[0]; i++){for(int j = 0; j <= num[1]; j++){for(int k = 0; k <= num[2]; k++){for(int l = 0; l <= num[3]; l++){int id = ha[i][j][k][l];for(int g = 0; g < size; g++){if(dp[id][g] == -1) continue;for(int h = 0; h < 4; h++){int nex;if(h == 0 && i == num[0]) continue;if(h == 1 && j == num[1]) continue;if(h == 2 && k == num[2]) continue;if(h == 3 && l == num[3]) continue;if(h == 0) nex = ha[i + 1][j][k][l];if(h == 1) nex = ha[i][j + 1][k][l];if(h == 2) nex = ha[i][j][k + 1][l];if(h == 3) nex = ha[i][j][k][l + 1];int add = node[node[g].next[h]].cnt;if(dp[nex][node[g].next[h]] < dp[id][g] + add){dp[nex][node[g].next[h]] = dp[id][g] + add;if(i + j + k + l + 1 == len) ans = max(ans , dp[nex][node[g].next[h]]);}}}}}}}printf("%d\n", ans);}}ac;
char s[45];
int main(){int ca = 1;while(~scanf("%d", &n) && n){ac.init();for(int i = 0; i < n; i++){scanf("%s", s);ac.insert(s);}ac.build();scanf("%s", s);printf("Case %d: ", ca++);ac.query(s);}return 0;
}

转载于:https://www.cnblogs.com/KirinSB/p/11195168.html

HDU 3341 Lost's revenge (AC自动机 + DP + 变进制/hash)题解相关推荐

  1. HDU - 3341 Lost's revenge(AC自动机+状压dp)

    题目链接:点击查看 题目大意:给出 n 个模式串,最后给出一个匹配串,问如何重新排列匹配串,可以使得匹配串尽可能多的匹配模式串 题目分析:因为是模式串和匹配串的匹配,所以考虑AC自动机,因为数据范围比 ...

  2. 【BZOJ】4861: [Beijing2017]魔法咒语 AC自动机+DP+矩阵快速幂

    [题意]给定n个原串和m个禁忌串,要求用原串集合能拼出的不含禁忌串且长度为L的串的数量.(60%)n,m<=50,L<=100.(40%)原串长度为1或2,L<=10^18. [算法 ...

  3. HDU 2296 Ring AC自动机 + DP

    题意:给你n个模式串,每个模式串有一个得分,让你构造出一个长度为N之内且分数最高的文本串;输出字典序列最小的. 解题思路:  AC自动机 + DP , 不过要输出字典序列最小,多开一个 一个三维字符串 ...

  4. uvalive4842(AC自动机+DP)

    题意: 给出猴子打字时打某个字母的概率,猴子最多可以敲键盘m次,问得到的长度是m的单词包含模式串的概率. 思路: AC自动机+dp. 首先,我们用模式串构造一个AC自动机,用dp[i]][j]表示当前 ...

  5. bzoj 1030: [JSOI2007]文本生成器(AC自动机+DP)

    1030: [JSOI2007]文本生成器 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 5187  Solved: 2136 [Submit][St ...

  6. HDU 3341 Lost's revenge(AC自动机+状态压缩DP)

    Description 给出N个优良的基因段,每段长度小于等于10,只含有AGCT四种碱基. 现给一段基因片段S,|S|<=40.对其重排列后,最多能含有多少个优良基因,基因段可以有公共部分 I ...

  7. hdu 6086 Rikka with String(AC自动机+状压dp)

    题目链接:hdu 6086 Rikka with String 题意: 给你n个只含01的串,和一个长度L,现在让你构造出满足s[i]≠s[|s|−i+1] for all i∈[1,|s|] ,长度 ...

  8. 【HDU 4511】小明系列故事——女友的考验(AC自动机+DP)

    Problem Description 终于放寒假了,小明要和女朋友一起去看电影.这天,女朋友想给小明一个考验,在小明正准备出发的时候,女朋友告诉他,她在电影院等他,小明过来的路线必须满足给定的规则: ...

  9. HDU - 4511 小明系列故事——女友的考验(AC自动机+dp)

    题目链接:点击查看 题目大意:小明在点 1 而小明的女朋友在点 n ,现在小明要去找女朋友,满足以下两个条件: 途径的序号满足严格递增 小明的女朋友给小明提出了 m 条路径是不允许走的 在满足上述两条 ...

  10. HDU - 2457 DNA repair(AC自动机+dp)

    题目链接:点击查看 题目大意:给出 n 个匹配串,再给出一个模式串,问最少修改模式串中多少个字母可以使得模式串中不含有任意一个匹配串 题目分析:因为又是模式串与匹配串的题目,虽然与一般意义上的匹配不太 ...

最新文章

  1. 阿里P9大佬总结必备的算法和工具,被10万算法工程师点赞
  2. bios get serialnumber 无法启动服务_联想笔记本BIOS升级教程
  3. [视频]怎样提升asp.net mvc 软件的性能 - 微软免费视频Improving ASP.NET MVC Application Performance...
  4. Serializable的作用
  5. linux下root密码修改方法
  6. [leetcode] 141.环形链表
  7. 测试Rockey 4 Smart加密锁的C语言代码
  8. 数据结构——队列的C++实现
  9. tmpwatch命令
  10. 文件和目录:access函数
  11. TextView的一些高级应用(自定义字体、显示多种颜色、添加阴影)
  12. QGraphicsView实现局部缩放,平移,并且能进行选中数据
  13. 软件技术基础复习提纲
  14. 关于TXT转CHM的完整解决方案
  15. establish connection
  16. 查看自己本地IP地址方法
  17. 超详细的《使用腾讯云移动直播开发连麦》
  18. iOS最安全?细数iOS曝过的安全漏洞|苹果|iOS|漏洞
  19. Android 编译之make基础(转)
  20. 音视频开发成长之路与音视频知识总结

热门文章

  1. 这是很简单的js拖拽方法
  2. 在centos6.5上编译安装httpd-2.4和2.4版本特性介绍
  3. 四、BDB JE学习(对java中内置对象的存储)
  4. android禁止下拉状态栏
  5. 生成订单30分钟未支付,则自动取消,该怎么实现?原来大公司的最有解是这样的!...
  6. Spring的Controller是单例还是多例,怎么保证并发的安全
  7. 它又又又来了,Fastjson 最新高危漏洞来袭!快升级吧
  8. Android性能优化系列---管理你的app内存(二)
  9. 一分钟了解微服务的好处和陷阱
  10. 是的,解禁了,是胜利还是嘲讽?