Lost's revenge
Time Limit: 5000MS Memory Limit: 65535KB 64bit IO Format: %I64d & %I64u

Description

Lost and AekdyCoin are friends. They always play "number game"(A boring game based on number theory) together. We all know that AekdyCoin is the man called "nuclear weapon of FZU,descendant of Jingrun", because of his talent in the field of number theory. So Lost had never won the game. He was so ashamed and angry, but he didn't know how to improve his level of number theory.

One noon, when Lost was lying on the bed, the Spring Brother poster on the wall(Lost is a believer of Spring Brother) said hello to him! Spring Brother said, "I'm Spring Brother, and I saw AekdyCoin shames you again and again. I can't bear my believers were being bullied. Now, I give you a chance to rearrange your gene sequences to defeat AekdyCoin!".

It's soooo crazy and unbelievable to rearrange the gene sequences, but Lost has no choice. He knows some genes called "number theory gene" will affect one "level of number theory". And two of the same kind of gene in different position in the gene sequences will affect two "level of number theory", even though they overlap each other. There is nothing but revenge in his mind. So he needs you help to calculate the most "level of number theory" after rearrangement.

Input

There are less than 30 testcases. 
For each testcase, first line is number of "number theory gene" N(1<=N<=50). N=0 denotes the end of the input file. 
Next N lines means the "number theory gene", and the length of every "number theory gene" is no more than 10. 
The last line is Lost's gene sequences, its length is also less or equal 40. 
All genes and gene sequences are only contains capital letter ACGT. 

Output

For each testcase, output the case number(start with 1) and the most "level of number theory" with format like the sample output.

Sample Input

3
AC
CG
GT
CGAT
1
AA
AAA
0

Sample Output

Case 1: 3
Case 2: 2
 
 
【题意】
  给定一些需要匹配的串,然后在给定一个目标串,现在可以通过交换目标串中任意两个位置的字符,要求最后生成的串匹配尽量多的匹配串,可以重复匹配。有重复的串的。
 
【分析】
  这题限定了每个字母选取的个数,上限为40。
  如果简单的表示状态的话,有41*41*41*41种情况,再加上DP的一维记录现在走到的节点的位置的话,就会爆空间。
  但我们会发现——其实很多都是没有用的,同时满足四个上限的话,很多情况都取不到,最多也就11*11*11*11种情况而已。
  但是每个字母的上限还是有40啊?怎么办呢? 就要用到k进制把状态压成一个十进制数。(k根据题目数据而定)
  k进制——类比10进制就能Y出来了。
  所以状态是14641种。
  然后DP,
  我的DP是,最外层for一共填了多少个字母,那么就可以保证DP大状态时小状态已经求出来了。(不会告诉你就这个我就纠结了很久啊QAQ)
  后面几个FOR都是枚举各个字母的选取(有点丑,但是觉得这样好打)
 
代码如下:
 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
#define Maxn 510
#define Maxl 15000
#define INF 0xfffffff
#define Mod 20090717 int n;
char s[];
int v[],k[],ln; struct node
{
// int cnt;
int fail,mark;
int son[];
}t[Maxn];int tot;
int num;
int p[]; void upd(int x)
{
// t[x].cnt=0;
t[x].mark=;
memset(t[x].son,,sizeof(t[x].son));
} int mymin(int x,int y) {return x<y?x:y;}
int mymax(int x,int y) {return x>y?x:y;} void read_trie()
{
scanf("%s",s+);
int len=strlen(s+);
int now=;
for(int i=;i<=len;i++)
{
if(s[i]=='C') s[i]='B';
else if(s[i]=='G') s[i]='C';
else if(s[i]=='T') s[i]='D';
int ind=s[i]-'A'+;
if(!t[now].son[ind])
{
t[now].son[ind]=++tot;
upd(tot);
}
now=t[now].son[ind];
if(i==len) t[now].mark++;
}
} queue<int > q;
void build_AC()
{
while(!q.empty()) q.pop();
q.push();
while(!q.empty())
{
int x=q.front();q.pop();
for(int i=;i<=;i++)
{
if(t[x].son[i])
{
t[t[x].son[i]].fail=x?t[t[x].fail].son[i]:;
q.push(t[x].son[i]);
}
else t[x].son[i]=t[t[x].fail].son[i];
}
t[x].mark+=t[t[x].fail].mark;
}
} int f[Maxn][Maxl];
int a[];
void dp()
{
memset(f,-,sizeof(f));
f[][]=;
int ans=;
for(int l=;l<=ln;l++) //选取的字母个数
for(int i=;i<=tot;i++) //走到节点i
for(a[]=mymax(l-v[]-v[]-v[],);a[]<=mymin(v[],l);a[]++)//if(f[i-1][j][l]!=0)
for(a[]=mymax(l-v[]-v[]-a[],);a[]<=mymin(v[],l);a[]++)
for(a[]=mymax(l-v[]-a[]-a[],);a[]<=mymin(v[],l);a[]++)
{
a[]=l-a[]-a[]-a[];
int now=a[]*k[]+a[]*k[]+a[]*k[]+a[];
if(f[i][now]==-) continue;
for(int j=;j<=;j++) if(a[j]+<=v[j])
{
// if(t[t[i].son[j]].mark)
f[t[i].son[j]][now+k[j]]=mymax(f[t[i].son[j]][now+k[j]],f[i][now]+t[t[i].son[j]].mark);
// else f[t[i].son[j]][now+k[j]]=mymax(f[t[i].son[j]][now+k[j]],f[i][now]);
ans=mymax(ans,f[t[i].son[j]][now+k[j]]);
}
}
printf("%d\n",ans);
} char ss[];
void init()
{
tot=;
upd();
for(int i=;i<=n;i++)
{
read_trie();
}
build_AC();
scanf("%s",ss+);
ln=strlen(ss+);
v[]=v[]=v[]=v[]=;
for(int i=;i<=ln;i++)
{
if(ss[i]=='C') ss[i]='B';
else if(ss[i]=='G') ss[i]='C';
else if(ss[i]=='T') ss[i]='D';
v[ss[i]-'A'+]++;
}
int maxx=(v[]+)*(v[]+)*(v[]+)*(v[]+);
k[]=(v[]+)*(v[]+)*(v[]+);
k[]=(v[]+)*(v[]+);
k[]=(v[]+);k[]=;
} int main()
{
int kase=;
while()
{
scanf("%d",&n);
if(n==) break;
init();
printf("Case %d: ",++kase);
dp();
}
return ;
}

[HDU3341]

2016-07-12 09:42:49

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

  1. hdu 2825 aC自动机+状压dp

    Wireless Password Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others ...

  2. BZOJ1559 [JSOI2009]密码 【AC自动机 + 状压dp】

    题目链接 BZOJ1559 题解 考虑到这是一个包含子串的问题,而且子串非常少,我们考虑\(AC\)自动机上的状压\(dp\) 设\(f[i][j][s]\)表示长度为\(i\)的串,匹配到了\(AC ...

  3. HDU 3247 Resource Archiver(AC自动机 + 状压DP + bfs预处理)题解

    题意:目标串n( <= 10)个,病毒串m( < 1000)个,问包含所有目标串无病毒串的最小长度 思路:貌似是个简单的状压DP + AC自动机,但是发现dp[1 << n][ ...

  4. zoj3545Rescue the Rabbit (AC自动机+状压dp+滚动数组)

    Time Limit: 10 Seconds      Memory Limit: 65536 KB Dr. X is a biologist, who likes rabbits very much ...

  5. hdu2825 Wireless Password(AC自动机+状压dp)

    Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission ...

  6. hdu 4057--Rescue the Rabbit(AC自动机+状压DP)

    题目链接 Problem Description Dr. X is a biologist, who likes rabbits very much and can do everything for ...

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

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

  8. UVALive - 4126 Password Suspects (AC自动机+状压dp)

    给你m个字符串,让你构造一个字符串,包含所有的m个子串,问有多少种构造方法.如果答案不超过42,则按字典序输出所有可行解. 由于m很小,所以可以考虑状压. 首先对全部m个子串构造出AC自动机,每个节点 ...

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

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

  10. HDU 2825 Wireless Password(AC自动机 + 状压DP)题解

    题意:m个密码串,问你长度为n的至少含有k个不同密码串的密码有几个 思路:状压一下,在build的时候处理fail的时候要用 | 把所有的后缀都加上. 代码: #include<cmath> ...

随机推荐

  1. RFC 文档(中文与英文)

    http://man.chinaunix.net/develop/rfc/default.htm https://www.rfc-editor.org/retrieve/ http://www.iet ...

  2. android 5.0 创建多用户 双开多开应用(2)

    上一讲 讲了如何创建一个user android 5.0 创建多用户 双开多开应用(1) 为什么要创建User  例如window 系统创建了一个user 会在当前用户下进行操作,而android 多 ...

  3. iOS UIKit:CollectionView之设计 (1)

    collection view(UICollectionView对象)使用灵活和可扩展的布局来描述有序的数据项,其一般情况下以网格的形式来展示内容,但并非一定如此. 1 基础 为了将数据展示在屏幕中, ...

  4. Weex命令

    1.下载安装 $ git clone https://github.com/alibaba/weex.git //通过brew安装node $ brew install node //通过node安装 ...

  5. java的真相

    所谓编译,就是把源代码“翻译”成目标代码——大多数是指机器代码——的过程.针对Java,它的目标代码不是本地机器代码,而是虚拟机代码. 编译原理里面有一个很重要的内容是编译器优化.所谓编译器优化是指, ...

  6. C#语法糖之第二篇: 参数默认值和命名参数 对象初始化器与集合初始化器

    今天继续写上一篇文章C#4.0语法糖之第二篇,在开始今天的文章之前感谢各位园友的支持,通过昨天写的文章,今天有很多园友们也提出了文章中的一些不足,再次感谢这些关心我的园友,在以后些文章的过程中不断的完 ...

  7. Android客户端中Bitmap的下载过程和缓存机制

    加载流程: if(内存命中){      从内存中读取 }else{      create AsyncTasks,task中的多个Runnable是通过堆栈先进后出的方式来调度,而非队列式的先进先出 ...

  8. js文件缓存之版本管理

    以前也做过不少项目,但从来就没有把关注的目光投向过js文件缓存.最近终于在毫无意识的情况下跳进了这个大坑. 近几个月来的工作是一个交易系统持续改进项目,迭代发布周期大约为2~3周.最近一次迭代是V16 ...

  9. SGU Volume 2

    SGU200.Cracking RSA------------------------★高斯消元 SGU207.Robbers -------------------------------数论 SG ...

  10. 忘记Mysql的root密码怎么办?

    解决方法: 1.打开cmd,用net start命令查看是否开启了mysql服务,如果开启,用net stop mysql 命令关闭mysql 2.进入mysql的安装目录下的bin目录,例如:E:\ ...