【HDOJ3341】Lost's revenge(AC自动机,DP)
题意:给出一个n个模式串,一个目标串,问把目标串重新排位最多能产生多少个模式串,可以重叠且所有串只包含A C G T。
n<=10,len[i]<=10
len(s)<=40
Cas<=30
思路:TLE,估计被卡常了
可以将题意理解为重新构造一个ACGT个数都与原目标串相同的新串,则目标串中有用的信息只有ACGT个数
建出Trie图,跑一遍AC自动机,再用一个二维dp[i,j]表示trie上i号节点,字母使用情况为j的模式串最多出现次数
其中j为状态压缩量,是一个四维的量压成一维,因为不压的话会MLE
dp[v,h(a,b,c,d)]=max(dp[v,h(a,b,c,d)],dp[u,h(a-1,b,c,d)]+size[v])等四种转移
其中v=map[u,i],size[v]表示trie上到v节点路径出现次数之和
边界条件dp[1,h(0,0,0,0)]=1
var map:array[..,..]of longint;
q,a,size,fa:array[..]of longint;
hash:array[..,..,..,..]of longint;
dp:array[..,..]of longint;
ch:string;
n,cnt,i,j,k,x,t,y,ans,len,s,cas,a1,c1,g1,t1,u,s1,v,s2,num:longint;
flag:boolean; function min(x,y:longint):longint;
begin
if x<y then exit(x);
exit(y);
end; function max(x,y:longint):longint;
begin
if x>y then exit(x);
exit(y);
end; procedure build;
var i,u:longint;
begin
u:=;
for i:= to len do
begin
if map[u,a[i]]= then
begin
inc(cnt); map[u,a[i]]:=cnt;
end;
u:=map[u,a[i]];
end;
inc(size[u]);
end; procedure acauto;
var t,w,i,p,son,u:longint;
begin
t:=; w:=; q[]:=;
while t<w do
begin
inc(t); u:=q[t];
size[u]:=size[u]+size[fa[u]];
for i:= to do
if map[u,i]> then
begin
son:=map[u,i];
p:=fa[u];
if u= then fa[son]:=
else fa[son]:=map[p,i];
inc(w); q[w]:=son;
end
else
begin
p:=fa[u];
if u= then map[u,i]:=
else map[u,i]:=map[p,i];
end;
end;
end; begin
assign(input,'hdoj3341.in'); reset(input);
assign(output,'hdoj3341.out'); rewrite(output);
while not eof do
begin
readln(n);
if n= then break;
inc(cas);
for i:= to cnt do
begin
size[i]:=; fa[i]:=;
end;
for i:= to cnt do
for j:= to do map[i,j]:=;
for i:= to a1 do
for j:= to c1 do
for k:= to g1 do
for x:= to t1 do hash[i,j,k,x]:=; cnt:=;
for i:= to n do
begin
readln(ch);
len:=length(ch);
for j:= to len do
begin
case ch[j] of
'A':a[j]:=;
'C':a[j]:=;
'G':a[j]:=;
'T':a[j]:=;
end;
end;
build;
end;
acauto;
readln(ch);
len:=length(ch); a1:=; c1:=; g1:=; t1:=;
for i:= to len do
begin
case ch[i] of
'A':inc(a1);
'C':inc(c1);
'G':inc(g1);
'T':inc(t1);
end;
end;
num:=;
for i:= to a1 do
for j:= to c1 do
for k:= to g1 do
for x:= to t1 do
begin
inc(num); hash[i,j,k,x]:=num;
end; for i:= to cnt do
for j:= to a1 do
for k:= to c1 do
for x:= to g1 do
for y:= to t1 do dp[i,hash[j,k,x,y]]:=-;
dp[,hash[,,,]]:=; ans:=;
for i:= to a1 do
for j:= to c1 do
for k:= to g1 do
for x:= to c1 do
begin
if i+j+k+x= then continue;
s1:=hash[i,j,k,x];
for u:= to cnt do
for t:= to do
begin
v:=map[u,t];
s2:=;
if (t=)and(i>=) then s2:=hash[i-,j,k,x]
else if (t=)and(j>=) then s2:=hash[i,j-,k,x]
else if (t=)and(k>=) then s2:=hash[i,j,k-,x]
else if (t=)and(x>=) then s2:=hash[i,j,k,x-];
if s2= then continue;
if dp[u,s2]=- then continue;
dp[v,s1]:=max(dp[v,s1],dp[u,s2]+size[v]);
ans:=max(ans,dp[v,s1]);
end;
end;
writeln('Case ',cas,': ',ans);
end;
close(input);
close(output);
end.
UPD(2018.10.27):C++重写 果然C++常数小
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<map>
#include<set>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
typedef unsigned int uint;
typedef unsigned long long ull;
typedef pair<int,int> PII;
typedef vector<int> VI;
#define fi first
#define se second
#define MP make_pair
#define N 610
#define M 7010
#define eps 1e-8
#define pi acos(-1)
#define oo 1e9
#define MOD 10007 int nxt[N][],q[N],size[N],fa[N],num[][][][],dp[N][],
A,C,G,T,len,cnt;
char b[M],ch[M]; void build()
{
int u=;
for(int i=;i<=len;i++)
{
int t;
if(b[i]=='A') t=;
if(b[i]=='C') t=;
if(b[i]=='G') t=;
if(b[i]=='T') t=;
if(!nxt[u][t]) nxt[u][t]=++cnt;
u=nxt[u][t];
}
size[u]++;
} void acauto()
{
int t=; int w=; q[]=;
while(t<w)
{
int u=q[++t];
size[u]+=size[fa[u]];
for(int i=;i<=;i++)
{
if(nxt[u][i])
{
int son=nxt[u][i];
int p=fa[u];
if(u==) fa[son]=;
else fa[son]=nxt[p][i];
q[++w]=son;
}
else
{
int p=fa[u];
if(u==) nxt[u][i]=;
else nxt[u][i]=nxt[p][i];
}
}
}
} int main()
{
//freopen("hdoj3341.in","r",stdin);
//freopen("hdoj3341.out","w",stdout);
int n;
int cas=;
A=C=G=T=cnt=;
while(scanf("%d",&n)!=EOF)
{
if(n==) break;
cas++;
for(int i=;i<=cnt;i++) size[i]=fa[i]=;
for(int i=;i<=cnt;i++)
for(int j=;j<=;j++) nxt[i][j]=;
for(int i=;i<=A;i++)
for(int j=;j<=C;j++)
for(int k=;k<=G;k++)
for(int x=;x<=T;x++) num[i][j][k][x]=;
cnt=;
for(int i=;i<=n;i++){scanf("%s",b+); len=strlen(b+); build();}
acauto();
scanf("%s",ch+);
len=strlen(ch+);
A=C=G=T=;
for(int i=;i<=len;i++)
{
if(ch[i]=='A') A++;
if(ch[i]=='C') C++;
if(ch[i]=='G') G++;
if(ch[i]=='T') T++;
}
int s=;
for(int i=;i<=A;i++)
for(int j=;j<=C;j++)
for(int k=;k<=G;k++)
for(int x=;x<=T;x++) num[i][j][k][x]=++s;
for(int i=;i<=cnt;i++)
for(int j=;j<=A;j++)
for(int k=;k<=C;k++)
for(int x=;x<=G;x++)
for(int y=;y<=T;y++) dp[i][num[j][k][x][y]]=-;
dp[][num[][][][]]=;
int ans=;
for(int i=;i<=A;i++)
for(int j=;j<=C;j++)
for(int k=;k<=G;k++)
for(int x=;x<=T;x++)
{
if(i+j+k+x==) continue;
int s1=num[i][j][k][x];
for(int u=;u<=cnt;u++)
for(int t=;t<=;t++)
{
int v=nxt[u][t];
int s2=;
if(t==&&i>=) s2=num[i-][j][k][x];
if(t==&&j>=) s2=num[i][j-][k][x];
if(t==&&k>=) s2=num[i][j][k-][x];
if(t==&&x>=) s2=num[i][j][k][x-];
if(s2==||dp[u][s2]==-) continue;
dp[v][s1]=max(dp[v][s1],dp[u][s2]+size[v]);
ans=max(ans,dp[v][s1]);
}
}
printf("Case %d: %d\n",cas,ans);
}
return ;
}
【HDOJ3341】Lost's revenge(AC自动机,DP)的更多相关文章
- 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 ...
- HDU3341 Lost's revenge(AC自动机&&dp)
一看到ACGT就会想起AC自动机上的dp,这种奇怪的联想可能是源于某道叫DNA什么的题的. 题意,给你很多个长度不大于10的小串,小串最多有50个,然后有一个长度<40的串,然后让你将这个这个长 ...
- hdu3341Lost's revenge(ac自动机+dp)
链接 类似的dp省赛时就做过了,不过这题卡内存,需要把当前状态hash一下,可以按进制来算出当前的状态,因为所有的状态数是不会超过10*10*10*10的,所以完全可以把这些存下来. 刚开始把trie ...
- HDU-3341-Lost's revenge(AC自动机, DP, 压缩)
链接: https://vjudge.net/problem/HDU-3341 题意: Lost and AekdyCoin are friends. They always play "n ...
- POJ1625 Censored!(AC自动机+DP)
题目问长度m不包含一些不文明单词的字符串有多少个. 依然是水水的AC自动机+DP..做完后发现居然和POJ2778是一道题,回过头来看都水水的... dp[i][j]表示长度i(在自动机转移i步)且后 ...
- HDU2296 Ring(AC自动机+DP)
题目是给几个带有价值的单词.而一个字符串的价值是 各单词在它里面出现次数*单词价值 的和,问长度不超过n的最大价值的字符串是什么? 依然是入门的AC自动机+DP题..不一样的是这题要输出具体方案,加个 ...
- HDU2457 DNA repair(AC自动机+DP)
题目一串DNA最少需要修改几个基因使其不包含一些致病DNA片段. 这道题应该是AC自动机+DP的入门题了,有POJ2778基础不难写出来. dp[i][j]表示原DNA前i位(在AC自动机上转移i步) ...
- hdu 4117 GRE Words AC自动机DP
题目:给出n个串,问最多能够选出多少个串,使得前面串是后面串的子串(按照输入顺序) 分析: 其实这题是这题SPOJ 7758. Growing Strings AC自动机DP的进阶版本,主题思想差不多 ...
- hdu 2457(ac自动机+dp)
题意:容易理解... 分析:这是一道比较简单的ac自动机+dp的题了,直接上代码. 代码实现: #include<stdio.h> #include<string.h> #in ...
- HDU 2425 DNA repair (AC自动机+DP)
DNA repair Time Limit: 5000/2000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
随机推荐
- jmeter(十六)Jmeter之Bean shell使用(二)
上一篇Jmeter之Bean shell使用(一)简单介绍了下Jmeter中的Bean shell,本文是对上文的一个补充,主要总结下常用的几种场景和方法,相信这些基本可以涵盖大部分的需求.本节内容如 ...
- AngularJS开发最常犯的10个错误
简介 AngularJS是目前最为活跃的Javascript框架之一,AngularJS的目标之一是简化开发过程,这使得AngularJS非常善于构建小型app原型,但AngularJS对于全功能的客 ...
- 构建一个.net的干货类库,以便于快速的开发 - 验证码
一个验证码对于一个网站的作用不言而喻,而随着技术的发展验证码的种类也开始多了起来,发展至今很多网站已经不再使用一种验证码,为满足需求程序猿就要写很多的方法来适应需求,今天我就来介绍我之前收集到的验证码 ...
- 组合模式和php实现
组合模式(有时候又叫做部分-整体模式): 将对象组合成树形结构以表示“部分整体”的层次结构.组合模式使得用户对单个对象和组合对象的使用具有一致性.它使我们树型结构的问题中,模糊了简单元素和复杂元素的概 ...
- git 学习笔记1
目前我属于粗放型的[学习者],接下来需要做一些改变,让自己更加规范.首先需要学习的就是版本控制系统,本科在工作室的时候使用过一点Subversion,不过到现在已经基本没有印象了.git现在越来越成为 ...
- 对象输入输出流ObjectInputStream、ObjectOutputStream(对象序列化与反序列化)
对象的输入输出流 : 主要的作用是用于写入对象信息与读取对象信息. 对象信息一旦写到文件上那么对象的信息就可以做到持久化了 对象的输出流: ObjectOutputStream 对象的输入流: Ob ...
- 迅为I.MX6开发板工业级嵌入式开发平台
迅为-i.MX6开发板是是基于ARM Cortex™-A9架构的高扩展性多核系列应用处理器, i.MX6系列芯片而且根据应用场合的不同,提供了可供选择的单核.双核和四核产品供客户选择.i.MX6系列的 ...
- laravel socialite微信登录注意
在token没有过期之前,重新走登录流程时会跳过callback,即不再重新登录,除了删除了客户端的token
- cut - 在文件的每一行中提取片断
总览 (SYNOPSIS) ../src/cut [OPTION]... [FILE]... 描述 (DESCRIPTION) 在 每个文件 FILE 的 各行 中, 把 提取的 片断 显示在 标准输 ...
- Axis1.4框架 实现webservice服务器和客户端
一:软件环境 win7旗舰版, Eclipse,JDK1.6,tomcat6.0,Axis1.4的包. 至于Axis1.4包网上可以下载,如果是在找不到可以留言给我. 二:摘要 将解压后的 axis- ...