题目链接:点击查看

题目大意:给出 n 个模式串,最后给出一个匹配串,问如何重新排列匹配串,可以使得匹配串尽可能多的匹配模式串

题目分析:因为是模式串和匹配串的匹配,所以考虑AC自动机,因为数据范围比较小,且是求最优解,所以考虑dp,因为匹配串的长度最多只有40,而不同的字符只有 4 种,所以可以开个五维dp转移状态,dp[ A ][ B ][ C ][ D ][ state ] 表示当四种字符的个数分别选取了 A,B,C,D 个时,状态为 state 时最多可以匹配的模式串,显然这样转移是正确的,不过问题是这样开数组会爆内存,但转念一想,其实并用不了这么多内存,因为 A + B + C +  D 是小于等于 40 的,所以我们可以选择对其进行哈希压缩空间,或者直接用进制的思想压缩,这样一来只需要开一个二维dp就可以满足条件了 dp[A,B,C,D][ state ] ,因为最多的种类数是 11*11*11*11,所以数组开这么大就够了,剩下的直接暴力更新就好了

还有一个小问题,就是需要注意一下上界的问题,不然会WA,添加一些 if 用来限制上界就好了

代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=510;char s[N];int dp[N][11*11*11*11+100],bit[4],num[4];//dp[state][A,B,C,D]int fail[N],cntword[N],trie[N][4],mp[150],cnt;void insert_word()
{int len=strlen(s);int pos=0;for(int i=0;i<len;i++){int to=mp[s[i]];if(!trie[pos][to])trie[pos][to]=++cnt;pos=trie[pos][to];}cntword[pos]++;
}void getfail()
{queue<int>q;for(int i=0;i<4;i++){if(trie[0][i]){fail[trie[0][i]]=0;q.push(trie[0][i]);}}while(!q.empty()){int cur=q.front();q.pop();cntword[cur]+=cntword[fail[cur]];for(int i=0;i<4;i++){if(trie[cur][i]){fail[trie[cur][i]]=trie[fail[cur]][i];q.push(trie[cur][i]);}elsetrie[cur][i]=trie[fail[cur]][i];}}
}void init()
{cnt=0;memset(cntword,0,sizeof(cntword));memset(trie,0,sizeof(trie));mp['A']=0,mp['C']=1,mp['G']=2,mp['T']=3;memset(dp,-1,sizeof(dp));memset(num,0,sizeof(num));memset(bit,0,sizeof(bit));
}int main()
{
#ifndef ONLINE_JUDGE
//    freopen("input.txt","r",stdin);
//    freopen("output.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);int n;int kase=0;while(scanf("%d",&n)!=EOF&&n){init();while(n--){scanf("%s",s);insert_word();}getfail();scanf("%s",s);int len=strlen(s);for(int i=0;i<len;i++)num[mp[s[i]]]++;bit[0]=1;bit[1]=num[0]+1;bit[2]=(num[0]+1)*(num[1]+1);bit[3]=(num[0]+1)*(num[1]+1)*(num[2]+1);dp[0][0]=0;for(int A=0;A<=num[0];A++)for(int B=0;B<=num[1];B++)for(int C=0;C<=num[2];C++)for(int D=0;D<=num[3];D++){int s=A*bit[0]+B*bit[1]+C*bit[2]+D*bit[3];for(int j=0;j<=cnt;j++)if(dp[j][s]>=0){for(int k=0;k<4;k++){int nj=trie[j][k];if(k==0&&A==num[0])continue;if(k==1&&B==num[1])continue;if(k==2&&C==num[2])continue;if(k==3&&D==num[3])continue;dp[nj][s+bit[k]]=max(dp[nj][s+bit[k]],dp[j][s]+cntword[nj]);}}}int ans=0;int s=bit[0]*num[0]+bit[1]*num[1]+bit[2]*num[2]+bit[3]*num[3];for(int i=0;i<=cnt;i++)ans=max(ans,dp[i][s]);printf("Case %d: %d\n",++kase,ans);}return 0;
}

HDU - 3341 Lost's revenge(AC自动机+状压dp)相关推荐

  1. 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|] ,长度 ...

  2. hdu 6086 -- Rikka with String(AC自动机 + 状压DP)

    题目链接 Problem Description As we know, Rikka is poor at math. Yuta is worrying about this situation, s ...

  3. HDU - 2825 Wireless Password(AC自动机+状压dp)

    题目链接:点击查看 题目大意:给出 m 个匹配串,问长度为 n 的字符串中,至少包含 k 个匹配串(可重叠)的字符串有多少个 题目分析:考虑到n,m,k都特别小,所以可以先用AC自动机将状态关系转移出 ...

  4. HDU - 2825 Wireless Password (AC自动机 + 状压dp)

    题目链接 题意 求至少包含KKK个给定字符串长度为NNN的字符串 思路 把所有可能的字符串建AC自动机,遍历所有节点dp[i][j][k]dp[i][j][k]dp[i][j][k] 表示以节点jjj ...

  5. HDU - 3247 Resource Archiver(AC自动机+状压dp+bfs)

    题目链接:点击查看 题目大意:给出 n 个目标串和 m 个病毒串,要求构造出一个长度最短的,且包含全部 n 个目标串,但是不能包含任意一个病毒串的01字符串,输出其最短长度 题目分析:比较综合的一道题 ...

  6. 【hdu2825】ac自动机 + 状压dp

    传送门 题目大意: 给你一些密码片段字符串,让你求长度为n,且至少包含k个不同密码片段串的字符串的数量. 题解: 因为密码串不多,可以考虑状态压缩 设dp[i][j][sta]表示长为i的字符串匹配到 ...

  7. AC自动机+状压dp hdu2825 Wireless Password

    传送门:点击打开链接 题意:有个密码长度为n,现在有m个魔力单词,要求密码中魔力单词的种类数>=k,问这种密码的种类数. 思路:和之前一样,我们会想到AC自动机去压缩状态,把状态给简化.然后我们 ...

  8. P4045-[JSOI2009]密码【AC自动机,状压dp】

    正题 题目链接:https://www.luogu.com.cn/problem/P4045 题目大意 给nnn个字符串,求有多少个长度为lll的字符串包含所有给出的字符串 解题思路 因为nnn很小, ...

  9. *【HDU - 4272 】LianLianKan (dfs 或 状压dp,贪心不行)

    题干: I like playing game with my friend, although sometimes looks pretty naive. Today I invent a new ...

最新文章

  1. PHP实现图片压缩的两则实例(转)
  2. 1.9 多态性:什么是多态?
  3. Git之Sourcetree的commit后回滚
  4. samba权限跟linux权限,linux之samba与linux权限
  5. MySQL常见函数介绍
  6. 图管够!灌篮高手、女儿国…阿里日_这帮程序员太会玩了!
  7. 跟小伙伴们做了个高效刷论文的小站
  8. python大作业爬虫_爬虫大作业
  9. git ignore 怎么添加和删除_Git删除已追踪文件,上传大文件到Github
  10. 前端开发工程师和美工 知识需求的区别
  11. html之css关于引入样式的优先级
  12. 获取指定路径,扫描路径下指定类(仿Spring)
  13. 蓝海灵豚医疗器械管理软件医用耗材专版
  14. R2V软件自动矢量化----体验篇
  15. 医院挂号系统代码_智慧医院中心是怎样做的?分诊叫号系统如何正确使用!
  16. 微信APP退款功能开发
  17. SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame
  18. 磁吸数据线的特点与优势
  19. power bi 雷达图_星载雷达与C波段地基雷达数据一致性个例分析 | 新文速递
  20. Promise: 手写Promise

热门文章

  1. wordpress archive.php,哪个网址将导致wordpress使用archive.php?
  2. J .U.C 中的原子操作类
  3. MyBatis创建SqlSession-怎么拿到一个SqlSessionTemplate?
  4. Spring 核心特性
  5. 数据库-in子句-exists子句
  6. 元组-元组变量的循环遍历
  7. SpringBoot_数据访问-整合MyBatis(二)-配置版MyBatis
  8. java imap 标记已读,JavaMail通过IMAP和POP3接收未读以及设置已读邮件
  9. AJAX框架眼镜店美瞳,PS完成对照片中人物的美瞳效果
  10. JVM--字节码执行引擎