题目大意:

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

这里很明显要用状态压缩当前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. Swift语言学习之学习资源

    (1) http://swift.sh (2) Let's Swift – WRITE THE CODE. CHANGE THE WORLD. http://letsswift.com (3)http ...

  2. gdufs 1237 最优分解问题

    题目链接:http://cstfs.gdufs.edu.cn:8080/JudgeOnline/problem.jsp?id=1237 (好像是内网的0.0) 简单来说,这道题目就是把一个数分解为若干 ...

  3. laravel各种路径的获取方法

    若Route中有Route::get('home/test', 'HomeController@index')->name('test'); ①视图中的href跳转 一.<a href=& ...

  4. hdu 5755(高斯消元——模线性方程组模板)

    PS. 看了大神的题解,发现确实可以用m个未知数的高斯消元做.因为确定了第一行的情况,之后所有行的情况都可以根据第一行推. 这样复杂度直接变成O(m*m*m) 知道了是高斯消元后,其实只要稍加处理,就 ...

  5. word2010表格中的内容怎么设置行距

    选中表格,然后根据箭头指示点击 弹出如下对话框,选择行距

  6. One Class SVM, SVDD(Support Vector Domain Description)(转)

    今天给大家介绍一下one class classification以及用SVDD(support vector domain description)做one class classification ...

  7. [转] Android OkHttp完全解析 是时候来了解OkHttp了

    http://blog.csdn.net/lmj623565791/article/details/47911083: 本文出自:[张鸿洋的博客] 一.概述 最近在群里听到各种讨论okhttp的话题, ...

  8. Java中的泛型方法

    泛型是什么意思在这就不多说了,而Java中泛型类的定义也比较简单,例如:public class Test<T>{}.这样就定义了一个泛型类Test,在实例化该类时,必须指明泛型T的具体类 ...

  9. css读书笔记3:定位元素

    定位元素要掌握css技术,核心就是要掌握元素定位. 一般把下面这条规则作为所有css样式表的第一条,初始化所有元素的内边距和外边距都为0: * {padding:0;margin:0;} 盒模型浏览器 ...

  10. mysql通过binlog日志来恢复数据

    简介 在生产的过程中有这么一个业务场景:比如我在2016-11-19 09:30:00 通过mysqldump的方式备份了数据库,但是在2016-11-19 10:30:00的时候数据库崩溃了,如果通 ...