题目大意:

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

这里很明显要用状态压缩当前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. Android开发面试经——6.常见面试官提问Android题②(更新中...)

    版权声明:本文为寻梦-finddreams原创文章,请关注:http://blog.csdn.net/finddreams 关注finddreams博客:http://blog.csdn.net/fi ...

  2. iOS开发 仿淘宝,京东商品详情3D动画

    - (void)show { [[UIApplication sharedApplication].windows[0] addSubview:self.projectView]; CGRect fr ...

  3. JavaScript中Cookie的用法

    Javascript中Cookie主要存储于客户端的计算机中,用于存放已访问的站点信息,Cookie最大约为4k.以下实例主要用于页面在刷新时保存数据,具体的用法如下所示: <html> ...

  4. java 零碎1

    1. java 程序的入口必须是 static 类型的,接口中不允许有 static , 而且接口中的方法必须是public. 2. java 回收主要针对的是堆区的回收. 3. java.exe 是 ...

  5. Unity 3D中的内存管理

    本文欢迎转载,但烦请保留此行出处信息:http://www.onevcat.com/2012/11/memory-in-unity3d/ Unity3D在内存占用上一直被人诟病,特别是对于面向移动设备 ...

  6. 从别人那淘的知识 深入剖析Java中的装箱和拆箱

    (转载的海子的博文   海子:http://www.cnblogs.com/dolphin0520/) 深入剖析Java中的装箱和拆箱 自动装箱和拆箱问题是Java中一个老生常谈的问题了,今天我们就来 ...

  7. 解决requestAnimationFrame的兼容问题

    写法: window.requestAnimFrame = (function () { return window.requestAnimationFrame || window.webkitReq ...

  8. GitHub学习资料

    GitHub账户注册注册了有一年多了(Joined on 13 Apr 2015),一直以来都是本地命令行上传到内网的Git服务器Gitlab.最近正好在学习新的编程语言,所以当初荒废的GitHub想 ...

  9. Java GC系列(4):垃圾回收监视和分析

    本文由 ImportNew - lomoxy 翻译自 javapapers. 目录 垃圾回收介绍 垃圾回收是如何工作的? 垃圾回收的类别 垃圾回收监视和分析 在这个Java GC系列教程中,让我们学习 ...

  10. 错误 undefined reference to __cxa_guard_acquire/release

    用gcc编译 c++ 程序时,出现错误 undefined reference to __cxa_guard_acquire linker error, 但是用icc可以正常编译, 问题出在stati ...