hdu 3341(ac自动机+状态压缩)
题意:容易理解...
思路:首先一开始容易想到要用到dp,开设一个dp[41][41][41][41][501]的数组来解决,但是明显内存已经超出范围了,于是就想如何减少内存呢?只要知道A、T、C、G其中三个的个数,则另一个也能算出,于是空间可以缩小到:41*41*41*500,但是还是不行啊!想了好久还是没找到方法,于是就问了一个大神,他的一个提示给了我灵感:虽然A、T、C、G的个数范围是[0,40],但是numa+numc+numg+numt的范围也是[0,40],于是就可以推出numa*numc*numg*numt的范围为[0,15000](自己写四个for循环可以算出最大为13000多),于是就可以压缩成一个dp[15000][501]的数组了。后来看了网上的方法,他们用了什么变进制,我表示现在还没看懂!!
代码实现:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<queue>
using namespace std;
struct node{
int next[4];
int fail;
int num;
void init()
{
memset(next,0,sizeof(next));
fail=0;
num=0;
}
}a[505];
int tot,n;
int hash[41][41][41][41];
int ta,tc,tg,tt;
int dp[15000][505];
char keyword[15];
char S[45];
int MAX(int a,int b)
{
return a>b?a:b;
}
void chushihua()
{
memset(dp,-1,sizeof(dp));
ta=tc=tg=tt=0;
tot=0;
a[0].init();
}
int hash1(char x)
{
if(x=='A')
return 0;
else if(x=='C')
return 1;
else if(x=='G')
return 2;
else
return 3;
}
void insert(char *str)//建立字典树
{
int index,p=0;
for(;*str!='\0';str++)
{
index=hash1(*str);
if(a[p].next[index]==0)
{
a[++tot].init();
a[p].next[index]=tot;
}
p=a[p].next[index];
}
a[p].num++;
}
void build_ac()//建立trie图
{
int i,p,cur,son;
queue<int>Q;
Q.push(0);
while(!Q.empty())
{
p=Q.front();
Q.pop();
for(i=0;i<4;i++)
{
if(a[p].next[i]!=0)
{
son=a[p].next[i];
cur=a[p].fail;
if(p==0)
a[son].fail=0;
else
{
while(cur&&a[cur].next[i]==0)
cur=a[cur].fail;
a[son].fail=a[cur].next[i];
}
if(a[a[son].fail].num)
a[son].num+=a[a[son].fail].num;
Q.push(son);
}
else
a[p].next[i]=a[a[p].fail].next[i];
}
}
}
void yasuo()//进行压缩
{
int i,j,k,l,num=0;
for(i=0;S[i]!='\0';i++)
if(S[i]=='A')
ta++;
else if(S[i]=='C')
tc++;
else if(S[i]=='G')
tg++;
else
tt++;
for(i=0;i<=ta;i++)
for(j=0;j<=tc;j++)
for(k=0;k<=tg;k++)
for(l=0;l<=tt;l++)
hash[i][j][k][l]=num++;
}
void solve(int zuhao)
{
int i,j,k,l,p,q,son,x1,x2,max=0;
dp[0][0]=0;
for(i=0;i<=ta;i++)
for(j=0;j<=tc;j++)
for(k=0;k<=tg;k++)
for(l=0;l<=tt;l++)
{
if(i+j+k+l==0)
continue;
x1=hash[i][j][k][l];//解压
for(p=0;p<=tot;p++)
{
for(q=0;q<4;q++)
{
if(q==0&&i-1>=0)
x2=hash[i-1][j][k][l];
else if(q==1&&j-1>=0)
x2=hash[i][j-1][k][l];
else if(q==2&&k-1>=0)
x2=hash[i][j][k-1][l];
else if(q==3&&l-1>=0)
x2=hash[i][j][k][l-1];
else
continue;
if(dp[x2][p]==-1)
continue;
son=a[p].next[q];
dp[x1][son]=MAX(dp[x1][son],dp[x2][p]+a[son].num);
if(dp[x1][son]>max)
max=dp[x1][son];
}
}
}
printf("Case %d: ",zuhao);
printf("%d\n",max);
}
int main()
{
int zuhao=0;
while(scanf("%d",&n)!=EOF&&n)
{
zuhao++;
chushihua();
getchar();
while(n--)
{
scanf("%s",keyword);
insert(keyword);
}
build_ac();
scanf("%s",S);
yasuo();
solve(zuhao);
}
return 0;
}
hdu 3341(ac自动机+状态压缩)的更多相关文章
- HDU 4511 (AC自动机+状态压缩DP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4511 题目大意:从1走到N,中间可以选择性经过某些点,比如1->N,或1->2-> ...
- hdu 4057(ac自动机+状态压缩dp)
题意:容易理解... 分析:题目中给的模式串的个数最多为10个,于是想到用状态压缩dp来做,它的状态范围为1-2^9,所以最大为2^10-1,那我们可以用:dp[i][j][k]表示长度为i,在tri ...
- hdu 2825(ac自动机+状态压缩dp)
题意:容易理解... 分析:在做这道题之前我做了hdu 4057,都是同一种类型的题,因为题中给的模式串的个数最多只能为10个,所以我们就很容易想到用状态压缩来做,但是开始的时候我的代码超时了dp时我 ...
- Lost's revenge HDU - 3341 AC自动机+DP(需要学会如何优雅的压缩状态)
题意: 给你n个子串和一个母串,让你重排母串最多能得到多少个子串出现在重排后的母串中. 首先第一步肯定是获取母串中每个字母出现的次数,只有A T C G四种. 这个很容易想到一个dp状态dp[i][A ...
- HDU 4057 Rescue the Rabbit ( AC自动机 + 状态压缩DP )
模板来自notonlysuccess. 模式串只有10个,并且重复出现的分值不累加,因此很容易想到状态压缩. 将模式串加入AC自动机,最多有10*100个状态. dp[i][j][k]:串长为i,在T ...
- Wireless Password - HDU 2825(ac自动机+状态压缩)
题目大意:有个人想破解他邻居的密码,他邻居告诉了一些关于这个密码的信息,并且给他一个单词集合,他用这些信息判断一下最少有多少种密码. 1->, 所有的密码都是有小写字母组成. 2->,密码 ...
- HDU 4758 Walk Through Squares( AC自动机 + 状态压缩DP )
题意:给你两个串A,B, 问一个串长为M+N且包含A和B且恰好包含M个R的字符串有多少种组合方式,所有字符串中均只含有字符L和R. dp[i][j][k][S]表示串长为i,有j个R,在自动机中的状态 ...
- POJ 3691 (AC自动机+状态压缩DP)
题目链接: http://poj.org/problem?id=3691 题目大意:给定N个致病DNA片段以及一个最终DNA片段.问最终DNA片段最少修改多少个字符,使得不包含任一致病DNA. 解题 ...
- bzoj1195 神奇的ac自动机+状态压缩dp
/* 难的不是ac自动机,是状态压缩dp 之前做了一两题类似题目,感觉理解的还不够透彻 */ #include<iostream> #include<cstdio> #incl ...
随机推荐
- hdu2544 最短路
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2544 最短路径DIJKSTRA #include<stdio.h> #include<m ...
- 读书笔记:7个示例科普CPU Cache
本文转自陈皓老师的个人博客酷壳:http://coolshell.cn/articles/10249.html 7个示例科普CPU Cache (感谢网友 @我的上铺叫路遥 翻译投稿) CPU cac ...
- lintcode 中等题:unique Binary Search Tree 不同的二叉查找树
题目 不同的二叉查找树 给出 n,问由 1...n 为节点组成的不同的二叉查找树有多少种? 样例 给出n = 3,有5种不同形态的二叉查找树: 1 3 3 2 1 \ / / / \ \ 3 2 1 ...
- lintcode 中等题:find the missing number 寻找缺失的数
题目 寻找缺失的数 给出一个包含 0 .. N 中 N 个数的序列,找出0 .. N 中没有出现在序列中的那个数. 样例 N = 4 且序列为 [0, 1, 3] 时,缺失的数为2. 注意 可以改变序 ...
- lintcode:Flip Bits 将整数A转换为B
题目: 将整数A转换为B 如果要将整数A转换为B,需要改变多少个bit位? 样例 如把31转换为14,需要改变2个bit位. ()10=()2 ()10=()2 挑战 你能想出几种方法? 解题: A- ...
- 漫谈C语言及如何学习C语言
抄自:http://my.oschina.net/apeng/blog/137911 目录:[ - ] 为什么要学习C语言? C语言学习方法 1,参考书籍 2,动手实验环境搭建 3,网络资源 附录 一 ...
- Git教程之版本回退(4)
现在,我们已经学会了修改文件,然后把修改提交到Git版本库,现在再次修改readme.txt文件如下:
- 88. Merge Sorted Array
题目: Given two sorted integer arrays A and B, merge B into A as one sorted array. Note:You may assume ...
- 转 Android的消息处理机制
来自:http://blog.csdn.net/andyhuabing/article/details/7368217 Windows编程的朋友可能知道Windows程序是消息驱动的,并且有全局的消息 ...
- hdu 1176 免费馅饼(nyist 613)
http://acm.hdu.edu.cn/showproblem.php?pid=1176 dp[i][j]:表示第i秒接j位置的馅饼的最大值. 三种状态: dp[i][j]=max(dp[i-1] ...