题目大意:

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

这里很明显要用状态压缩当前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. iOS开发之Xcode 6更新默认不支持armv7s架构

    最近一次的Xcode 6更新默认不再支持arm7s架构,究竟是要废除不用呢还是仅仅只是一个疏忽? 目前的Xcode 6配置里定义${ARCHS_STANDARD}为armv7, arm64,当然这个定 ...

  2. Objective-C与C++的区别

    1.两者的最大相同:都是从C演化而来的面相对象语言,两者都兼容标准C语言 2.两者的最大不同:Objective-C提供了运行期动态绑定机制,而C++是编译静态绑定,并且通过嵌入类(多重继承)和虚函数 ...

  3. yum的使用及配置

    yum的使用及配置 文章来源:http://www.ilanni.com/?p=9032 最近由于服务器需求,需要在公司内网搭建内网yum源. 搭建内网yum源需要分以下几个步骤,如下: 1. yum ...

  4. 转!!URL和URI区别

    URI,URL,URN 从上面的那幅图可以看出来,一共有三个不同的概念URI,URL,URN.这讨论这样的问题时,最好的方法就是回到原点啊,这里我们在RFC 3986: Uniform Resourc ...

  5. 配置tomcat,java运行环境

    1.下载JDK,安装 官网下载地址:http://java.sun.com/javase/downloads/index.jsp 下载后,安装,选择你想把JDK安装的目录: 比如:JDK安装目录:E: ...

  6. $.each 与$().each()

    在jquery中,遍历对象和数组,经常会用到$().each和$.each(),两个方法.两个方法是有区别的,从而这两个方法在针对不同的操作上,显示了各自的特点. $().each,对于这个方法,在d ...

  7. Hbase之原子性插入

    /** * Created by similarface on 16/8/16. */ import java.io.IOException; import org.apache.hadoop.con ...

  8. electron小例子

    说明:该例子主要实现把输入框中的文字保存到本地的文本文档中. 在main中添加几句代码 const ipcMain = electron.ipcMain; const dialog = electro ...

  9. css清除默认样式和设置公共样式

    /*公共样式--开始*/ html, body, div, ul, li, h1, h2, h3, h4, h5, h6, p, dl, dt, dd, ol, form, input, textar ...

  10. jmeter 使用URL重写处理用户会话

    如果您的web应用程序使用URL重写而不是cookie保存会话信息, 那么你需要做一些额外的工作来测试你的网站. 正确应对URL重写,JMeter需要解析HTML 接收从服务器和检索独特的会话ID,使 ...