题目是给一个DNA重新排列使其包含最多的数论基因。

考虑到内存大概就只能这么表示状态:

dp[i][A][C][G][T],表示包含各碱基个数为ACGT且当前后缀状态为自动机第i的结点的字符串最多的数论基因数

其中ACGT可以hash成一个整数(a*C*G*T+c*G*T+g*T+T),这样用二维数组就行了,而第二维最多也就11*11*11*11个。

接下来转移依然是我为人人型,我是丢进一个队列,用队列来更新状态的值。

这题果然挺卡常数的,只好手写队列,最后4500msAC,还是差点超时,代码也搞得挺乱的。

 #include<cstdio>
#include<cstring>
using namespace std;
int tn,ch[][],fail[],flag[];
int idx[];
void insert(char *s){
int x=;
for(int i=; s[i]; ++i){
int y=idx[s[i]];
if(ch[x][y]==) ch[x][y]=++tn;
x=ch[x][y];
}
++flag[x];
}
int que[];
void init(){
memset(fail,,sizeof(fail));
int front=,rear=;
for(int i=; i<; ++i){
if(ch[][i]) que[rear++]=ch[][i];
}
while(front!=rear){
int x=que[front++];
for(int i=; i<; ++i){
if(ch[x][i]) que[rear++]=ch[x][i],fail[ch[x][i]]=ch[fail[x]][i],flag[ch[x][i]]+=flag[ch[fail[x]][i]];
else ch[x][i]=ch[fail[x]][i];
}
}
}
int d[][];
int quex[*],quey[*];
int main(){
idx['A']=; idx['C']=; idx['G']=; idx['T']=;
char str[];
int n,cse=;
while(~scanf("%d",&n) && n){
tn=;
memset(ch,,sizeof(ch));
memset(flag,,sizeof(flag));
while(n--){
scanf("%s",str);
insert(str);
}
init();
scanf("%s",str);
int times[]={};
for(int i=; str[i]; ++i){
++times[idx[str[i]]];
}
int tcal0=(times[]+)*(times[]+)*(times[]+);
int tcal1=(times[]+)*(times[]+);
int tcal2=(times[]+);
memset(d,-,sizeof(d));
d[][]=;
int front=,rear=,x,y,ny,cnt[];
quex[rear]=; quey[rear]=; ++rear;
while(front!=rear){
x=quex[front]; y=quey[front]; ++front;
ny=y;
cnt[]=ny/tcal0;
ny-=cnt[]*tcal0;
cnt[]=ny/tcal1;
ny-=cnt[]*tcal1;
cnt[]=ny/tcal2;
cnt[]=ny-cnt[]*tcal2;
for(int i=; i<; ++i){
if(cnt[i]>=times[i]) continue;
++cnt[i];
ny=cnt[]*tcal0+cnt[]*tcal1+cnt[]*tcal2+cnt[];
if(d[ch[x][i]][ny]==-){
d[ch[x][i]][ny]=d[x][y]+flag[ch[x][i]];
quex[rear]=ch[x][i]; quey[rear]=ny; ++rear;
}else if(d[ch[x][i]][ny]<d[x][y]+flag[ch[x][i]]){
d[ch[x][i]][ny]=d[x][y]+flag[ch[x][i]];
}
--cnt[i];
}
}
y=times[]*tcal0+times[]*tcal1+times[]*tcal2+times[];
int res=;
for(int x=; x<=tn; ++x){
if(res<d[x][y]) res=d[x][y];
}
printf("Case %d: %d\n",++cse,res);
}
return ;
}

HDU3341 Lost's revenge(AC自动机+DP)的更多相关文章

  1. HDU3341 Lost's revenge(AC自动机&&dp)

    一看到ACGT就会想起AC自动机上的dp,这种奇怪的联想可能是源于某道叫DNA什么的题的. 题意,给你很多个长度不大于10的小串,小串最多有50个,然后有一个长度<40的串,然后让你将这个这个长 ...

  2. HDU 3341 Lost's revenge AC自动机+dp

    Lost's revenge Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)T ...

  3. HDU-3341-Lost's revenge(AC自动机, DP, 压缩)

    链接: https://vjudge.net/problem/HDU-3341 题意: Lost and AekdyCoin are friends. They always play "n ...

  4. hdu3341Lost's revenge(ac自动机+dp)

    链接 类似的dp省赛时就做过了,不过这题卡内存,需要把当前状态hash一下,可以按进制来算出当前的状态,因为所有的状态数是不会超过10*10*10*10的,所以完全可以把这些存下来. 刚开始把trie ...

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

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

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

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

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

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

  8. hdu 4117 GRE Words AC自动机DP

    题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...

  9. hdu 2457(ac自动机+dp)

    题意:容易理解... 分析:这是一道比较简单的ac自动机+dp的题了,直接上代码. 代码实现: #include<stdio.h> #include<string.h> #in ...

  10. HDU 2425 DNA repair (AC自动机+DP)

    DNA repair Time Limit: 5000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

随机推荐

  1. Linux解压安装与卸载

    linux tar.gz zip 解压缩 压缩命令 linux下安装软件主要有这么几种: 1.自动安装: yum install package 2.用二进制文件安装:rpm -ivh file.rp ...

  2. C++中的memset()函数 ------------转自:http://www.360doc.com/content/10/1006/18/1704901_58866679.shtml

    memset()函数可以对大内存的分配进行很方便的操作(初始化),所谓“初始化”,当然是指将你定义的变量或申请的空间赋予你所期望的值,例如语句int i=0;就表明定义了一个变量i,并初始化为0:如果 ...

  3. [codeforces 528]B. Clique Problem

    [codeforces 528]B. Clique Problem 试题描述 The clique problem is one of the most well-known NP-complete ...

  4. Python os.system 和 os.popen的区别

    (1) os.system # 仅仅在一个子终端运行系统命令,而不能获取命令执行后的返回信息 system(command) -> exit_statusExecute the command ...

  5. ubuntu12.04 Daemon的简单实现

    使用命令 start-stop-daemon 官方文档:http://manpages.ubuntu.com/manpages/lucid/en/man8/start-stop-daemon.8.ht ...

  6. 数学复习 ---- Mathematics Notes: A Programmer's Perspective ---- by Orzer ---- 我是沙茶

    今年是好没长进的一年呢..只学了些基本的方法.. 本文记号0] x:p x类型为p1] f(x) 表示一个函数2] (n_1,n_2,...) 表示多元组,特别的,(n)表示一个一元组3] x 表示一 ...

  7. XShell上传下载命令

    参考:https://www.centos.bz/2012/12/xshell-securecrtrz-sz-upload-download/ 上传文件时,执行rz就会弹出文件选择对话框来选择文件.下 ...

  8. iOS 第三方自定义Alertview项目MBProcessHud中的重要代码分析

    做ios,弹出一个自定义的alertview挺常见的.ios7以前,我们可以对系统的UIAlertView进行一点操作,实现一点简单的定制,但是ios7不再允许我们这样做了.因此,我们需要自己创建一个 ...

  9. 六间房 繁星 酷我 来疯 秀吧 新浪秀 直播播放器 Live 1.2

    适合用于进行录制的时候 特别说明: 安装 falsh play 19 时 不能正常播放 每个按钮都有提示,不详细说明 下载地址 http://pan.baidu.com/s/1i32ETIt 下载地址 ...

  10. Emacs 从入门到精通

    1 前言 不想再说废话了,既然你会阅读这篇文档,说明你多少对Emacs有 些兴趣,或者已 经非常熟悉Emacs的基础操作了,并且希望有所提高.因此我不需要再把"编辑器 之神,还是神的编辑器& ...