题目大意:

调整基因的顺序,希望使得最后得到的基因包含有最多的匹配串基因,使得所能达到的智商最高

这里很明显要用状态压缩当前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自动机的更多相关文章

  1. 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 ...

  2. HDU 1074 (状态压缩DP)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1074 题目大意:有N个作业(N<=15),每个作业需耗时,有一个截止期限.超期多少天就要扣多少 ...

  3. hdu 4284 状态压缩dp

    题意: 有N 个点的无向图,要去其中 h个地点做事,做事需要先办理护照,之后可以挣一定数量的钱,知道了一开始有的总钱数,和 一些城市之间           道路的花费,问可不可以在 指定的 h 个城 ...

  4. hdu 2167 状态压缩dp

    /* 状态转移方程:dp[i][j]=Max(dp[i][j],dp[i-1][k]+sum[i][j]); */ #include<stdio.h> #include<string ...

  5. HDU 4856 (状态压缩DP+TSP)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4856 题目大意:有一个迷宫.迷宫里有些隧道,每个隧道有起点和终点,在隧道里不耗时.出隧道就耗时,你的 ...

  6. HDU 4640 状态压缩DP 未写完

    原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4640 解题思路: 首先用一个简单的2^n*n的dp可以求出一个人访问一个给定状态的最小花费,因为这i个 ...

  7. 2016"百度之星" - 初赛(Astar Round2A)1002 / HDU 5691 状态压缩DP

    Sitting in Line Problem Description   度度熊是他同时代中最伟大的数学家,一切数字都要听命于他.现在,又到了度度熊和他的数字仆人们玩排排坐游戏的时候了.游戏的规则十 ...

  8. HDU 5067 (状态压缩DP+TSP)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5067 题目大意:蓝翔挖掘机挖石子.把地图上所有石子都运回起点,问最少耗时. 解题思路: 首先得YY出 ...

  9. hdu 4539(状态压缩dp)

    题意:曼哈顿距离是指:|x1-x2|+|y1-y2|,只要知道这个概念题意就懂了. 分析:这道题与前面做的几道题有所不同,因为当前行不仅与前一行有关,而且与前两行有关,所以我们开数组的时候还要记录前两 ...

随机推荐

  1. git命令之git rebase 的用法

    rebase 假设你现在基于远程分支"origin",创建一个叫"mywork"的分支. $ git checkout -b mywork origin 现在我 ...

  2. 闲谈--心态 (zhuan)

    http://blog.csdn.net/marksinoberg/article/details/53261034 ***************************************** ...

  3. HA功能中ZKFC对NN状态的控制

    ZKFC : zookeeper FailoverController NN : name node Hadoop 2.0 HA架构图: FC是要和NN一一对应的,两个NN就要部署两个FC.它负责监控 ...

  4. HBase 的存储结构

    HBase 的存储结构 2016-10-17 杜亦舒 HBase 中的表常常是超级大表,这么大的表,在 HBase 中是如何存储的呢?HBase 会对表按行进行切分,划分为多个区域块儿,每个块儿名为  ...

  5. jquery 全选功能

    1.直接全选(复选框名字要统一) <input type="CHECKBOX" id="cbSelectAll" onclick="$('inp ...

  6. java 集合(Map)

    -------------------|Map  储存的数据都是以键值对的形式,键不可重复,值可重复. ----------------------------| HashMap ---------- ...

  7. Python--关于dict

    慕课网<Python 入门>学习笔记 1.dict 特性 dict用花括号{}表示,然后按照 key: value, 写出来即可.最后一个 key: value 的逗号可以省略. ①.di ...

  8. 【转】HTML, CSS和Javascript调试入门

    转 http://www.cnblogs.com/PurpleTide/archive/2011/11/25/2262269.html HTML, CSS和Javascript调试入门 本文介绍一些入 ...

  9. JavaScript中给对象添加函数的方式

    1. function 类名(){ this.属性: } var 对象名=new 类名(): function 函数名(){ //执行代码 } 对象名.属性名=函数名: 对象名.属性名(): func ...

  10. java之如何实现调用启动一个可执行文件,exe

    /* * 运行可执行文件:.exe * 当要执行一个本地机器上的可执行文件时, * 可以使用java.lang包中的Runtime类,首先使用Runtime类,首先 * 使用Runtime类声明一个对 ...