HDU 3341 状态压缩DP+AC自动机
题目大意:
调整基因的顺序,希望使得最后得到的基因包含有最多的匹配串基因,使得所能达到的智商最高
这里很明显要用状态压缩当前AC自动机上点使用了基因的情况所能达到的最优状态
我最开始对于状态的保存是,针对基因的个数转化为最小的二进制个数保存,但是浪费了很多二进制位,比如8 -> 1000,那么之后的1001,1010...1111都没用到
就MLE了
然后自己只能在压缩
比如数量为2 , 3 , 4 , 5
那么jz[0] = 1 , jz[1] = 2+1 , jz[2] = 2*1+3*3+1 , jz[3] = 2*1+3*3+4*12+1
那么可以根据这种进制进行解码转码了
那么状态数就能通过解码转码轻松获得了
可能自己写的比较挫吧,跑c++跑不过,g++倒是完全没问题
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <queue>
using namespace std;
#define LL long long
#define clr(x) memset(x , 0 , sizeof(x))
#define MAX_SIZE 502
#define CHAR_SIZE 4
const int MAX_STATE = ;
int n;
char str[]; int Hash(char c){
if(c=='A') return ;
else if(c == 'C') return ;
else if(c=='G') return ;
else return ;
} struct AC_Machine{
int sz , ch[MAX_SIZE][CHAR_SIZE] , fail[MAX_SIZE], val[MAX_SIZE] , gene[MAX_SIZE];
void init(){
sz = ;
clr(ch[]) , clr(val);
gene[] = ;
} void insert(char *s){
int n=strlen(s) , u=;
for(int i= ; i<n ; i++){
int c = Hash(s[i]);
if(!ch[u][c]){
clr(ch[sz]);
val[sz] = gene[sz] = ;
ch[u][c] = sz++;
}
u = ch[u][c];
}
gene[u] ++;
val[u] = ;
} void get_fail(){
queue<int> Q;
fail[] = ;
for(int c= ; c<CHAR_SIZE ; c++){
int u = ch[][c];
if(u) {Q.push(u);fail[u]=;}
}
while(!Q.empty()){
int r = Q.front();
val[r] |= val[fail[r]];
Q.pop();
for(int c= ; c<CHAR_SIZE ; c++){
int u = ch[r][c];
if(!u){ch[r][c]=ch[fail[r]][c] ; continue;}
fail[u] = ch[fail[r]][c];
Q.push(u);
}
}
}
}ac; int dp[MAX_SIZE][MAX_STATE];
int cnt[] , jz[];
int code[] , save[];
void decode(int state)
{
for(int i= ; i>= ; i--){
code[i] = state/jz[i];
state -= code[i]*jz[i];
}
} int encode(int *code)
{
int ret = ;
for(int i= ; i>= ; i--) ret+=code[i]*jz[i];
return ret;
} void DP()
{
int all = encode(cnt);
for(int i= ; i<=all ; i++)
for(int j= ; j<ac.sz ; j++) dp[j][i] = -;
dp[][] = ;
for(int i= ; i<=all ; i++){
for(int j= ; j<ac.sz ; j++){
if(dp[j][i]<) continue;
decode(i);
for(int k= ; k< ; k++){
if(code[k]>=cnt[k]) continue;
int v = ac.ch[j][k];
int tmp = v , num=;
while(tmp&&ac.val[tmp]){
if(ac.gene[tmp]) num+=ac.gene[tmp];
tmp = ac.fail[tmp];
}
code[k]++;
int newst = encode(code);
code[k]--;
dp[v][newst] = max(dp[j][i]+num , dp[v][newst]);
}
}
}
} void solve()
{
int len = strlen(str);
memset(cnt , , sizeof(cnt));
for(int i= ; i<len ; i++) cnt[Hash(str[i])]++;
jz[] = , jz[] = cnt[]+ , jz[] = +cnt[]+cnt[]*jz[] , jz[] = cnt[]*jz[]+jz[];
DP();
} int main()
{
// freopen("in.txt" , "r" , stdin);
int cas = ;
while(scanf("%d" , &n) , n)
{
ac.init();
for(int i= ; i<n ; i++){
scanf("%s" , str);
ac.insert(str);
}
ac.get_fail();
scanf("%s" , str);
solve();
int all = encode(cnt);
int ret = -;
for(int i= ; i<ac.sz ; i++) ret = max(ret , dp[i][all]);
printf("Case %d: %d\n" , ++cas , ret);
}
return ;
}
HDU 3341 状态压缩DP+AC自动机的更多相关文章
- 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 ...
- HDU 1074 (状态压缩DP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1074 题目大意:有N个作业(N<=15),每个作业需耗时,有一个截止期限.超期多少天就要扣多少 ...
- hdu 4284 状态压缩dp
题意: 有N 个点的无向图,要去其中 h个地点做事,做事需要先办理护照,之后可以挣一定数量的钱,知道了一开始有的总钱数,和 一些城市之间 道路的花费,问可不可以在 指定的 h 个城 ...
- hdu 2167 状态压缩dp
/* 状态转移方程:dp[i][j]=Max(dp[i][j],dp[i-1][k]+sum[i][j]); */ #include<stdio.h> #include<string ...
- HDU 4856 (状态压缩DP+TSP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4856 题目大意:有一个迷宫.迷宫里有些隧道,每个隧道有起点和终点,在隧道里不耗时.出隧道就耗时,你的 ...
- HDU 4640 状态压缩DP 未写完
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4640 解题思路: 首先用一个简单的2^n*n的dp可以求出一个人访问一个给定状态的最小花费,因为这i个 ...
- 2016"百度之星" - 初赛(Astar Round2A)1002 / HDU 5691 状态压缩DP
Sitting in Line Problem Description 度度熊是他同时代中最伟大的数学家,一切数字都要听命于他.现在,又到了度度熊和他的数字仆人们玩排排坐游戏的时候了.游戏的规则十 ...
- HDU 5067 (状态压缩DP+TSP)
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5067 题目大意:蓝翔挖掘机挖石子.把地图上所有石子都运回起点,问最少耗时. 解题思路: 首先得YY出 ...
- hdu 4539(状态压缩dp)
题意:曼哈顿距离是指:|x1-x2|+|y1-y2|,只要知道这个概念题意就懂了. 分析:这道题与前面做的几道题有所不同,因为当前行不仅与前一行有关,而且与前两行有关,所以我们开数组的时候还要记录前两 ...
随机推荐
- Activtiy
Class Overview An activity is a single, focused thing that the user can do. Almost all activities in ...
- jQuery DOM基础
jQuery DOM基础 1.对元素内容的获取和修改: 表单用value(),普通元素用html()和text(). html() html(value)设置和获取html内容,有html标签会自动 ...
- Oracle一个用户查询另一个用户的表数据
1.两个用户是在不同的库,需要建立dblink 2.属于同一个库的不同用户 1)方法一:使用"用户名."的方式访问 例如:要从USER1账号访问USER2中的表TABLE2 A. ...
- 转:程序员最值得关注的10个C开源项目
程序员最值得关注的10个C开源项目 1. Webbench Webbench 是一个在 linux 下使用的非常简单的网站压测工具.它使用 fork ()模拟多个客户端同时访问我们设定的 URL,测试 ...
- java实现数据库连接池
package com.kyo.connection; import java.sql.Connection; import java.sql.DatabaseMetaData; import jav ...
- QQ聊天即时代码
QQ即时聊天代码:[需对方已经即时聊天工具功能 开通入口http://shang.qq.com/v3/widget.html] tencent://Message/?Uin=84065994& ...
- 转!!java泛型概念(泛型类,接口,方法)
一. 泛型概念的提出(为什么需要泛型)? 首先,我们看下下面这段简短的代码: 1 public class GenericTest { 2 3 public static void main(Stri ...
- iOS开发 判断用户是否开启了热点
- (BOOL)achiveUserHotspotOpening { return [UIApplication sharedApplication].statusBarFrame.size.heig ...
- HBase之过滤器
filter ==> SQL 中的Where filter的执行流程: 过滤器在客户端创建,然后通过RPC发送到服务器上,由服务器执行 基础过滤器: 比较器: Comparator D ...
- const修饰指针
关于const修饰指针的情况,一般分为如下4种情况: ; const int *a =&b; //情况1 int const *a =&b; //情况2 int* const a =& ...