zoukankan      html  css  js  c++  java
  • 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++倒是完全没问题

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <cmath>
      5 #include <queue>
      6 using namespace std;
      7 #define LL long long
      8 #define clr(x) memset(x , 0 , sizeof(x))
      9 #define MAX_SIZE 502
     10 #define CHAR_SIZE 4
     11 const int MAX_STATE = 100000;
     12 int n;
     13 char str[50];
     14 
     15 int Hash(char c){
     16     if(c=='A') return 0;
     17     else if(c == 'C') return 1;
     18     else if(c=='G') return 2;
     19     else return 3;
     20 }
     21 
     22 struct AC_Machine{
     23     int sz , ch[MAX_SIZE][CHAR_SIZE] , fail[MAX_SIZE], val[MAX_SIZE] , gene[MAX_SIZE];
     24     void init(){
     25         sz = 1;
     26         clr(ch[0]) , clr(val);
     27         gene[0] = 0;
     28     }
     29 
     30     void insert(char *s){
     31         int n=strlen(s) , u=0;
     32         for(int i=0 ; i<n ; i++){
     33             int c = Hash(s[i]);
     34             if(!ch[u][c]){
     35                 clr(ch[sz]);
     36                 val[sz] = gene[sz] = 0;
     37                 ch[u][c] = sz++;
     38             }
     39             u = ch[u][c];
     40         }
     41         gene[u] ++;
     42         val[u] = 1;
     43     }
     44 
     45     void get_fail(){
     46         queue<int> Q;
     47         fail[0] = 0;
     48         for(int c=0 ; c<CHAR_SIZE ; c++){
     49             int u = ch[0][c];
     50             if(u) {Q.push(u);fail[u]=0;}
     51         }
     52         while(!Q.empty()){
     53             int r = Q.front();
     54             val[r] |= val[fail[r]];
     55             Q.pop();
     56             for(int c=0 ; c<CHAR_SIZE ; c++){
     57                 int u = ch[r][c];
     58                 if(!u){ch[r][c]=ch[fail[r]][c] ; continue;}
     59                 fail[u] = ch[fail[r]][c];
     60                 Q.push(u);
     61             }
     62         }
     63     }
     64 }ac;
     65 
     66 int dp[MAX_SIZE][MAX_STATE];
     67 int cnt[4] , jz[4];
     68 int code[4] , save[4];
     69 void decode(int state)
     70 {
     71     for(int i=3 ; i>=0 ; i--){
     72         code[i] = state/jz[i];
     73         state -= code[i]*jz[i];
     74     }
     75 }
     76 
     77 int encode(int *code)
     78 {
     79     int ret = 0;
     80     for(int i=3 ; i>=0 ; i--) ret+=code[i]*jz[i];
     81     return ret;
     82 }
     83 
     84 void DP()
     85 {
     86     int all = encode(cnt);
     87     for(int i=0 ; i<=all ; i++)
     88         for(int j=0 ; j<ac.sz ; j++) dp[j][i] = -1;
     89     dp[0][0] = 0;
     90     for(int i=0 ; i<=all ; i++){
     91         for(int j=0 ; j<ac.sz ; j++){
     92             if(dp[j][i]<0) continue;
     93             decode(i);
     94             for(int k=0 ; k<4 ; k++){
     95                 if(code[k]>=cnt[k]) continue;
     96                 int v = ac.ch[j][k];
     97                 int tmp = v , num=0;
     98                 while(tmp&&ac.val[tmp]){
     99                     if(ac.gene[tmp]) num+=ac.gene[tmp];
    100                     tmp = ac.fail[tmp];
    101                 }
    102                 code[k]++;
    103                 int newst = encode(code);
    104                 code[k]--;
    105                 dp[v][newst] = max(dp[j][i]+num , dp[v][newst]);
    106             }
    107         }
    108     }
    109 }
    110 
    111 void solve()
    112 {
    113     int  len = strlen(str);
    114     memset(cnt , 0 , sizeof(cnt));
    115     for(int i=0 ; i<len ; i++) cnt[Hash(str[i])]++;
    116     jz[0] = 1 , jz[1] = cnt[0]+1 , jz[2] = 1+cnt[0]+cnt[1]*jz[1] , jz[3] = cnt[2]*jz[2]+jz[2];
    117     DP();
    118 }
    119 
    120 int main()
    121 {
    122    // freopen("in.txt" , "r" , stdin);
    123     int cas = 0;
    124     while(scanf("%d" , &n) , n)
    125     {
    126         ac.init();
    127         for(int i=0 ; i<n ; i++){
    128             scanf("%s" , str);
    129             ac.insert(str);
    130         }
    131         ac.get_fail();
    132         scanf("%s" , str);
    133         solve();
    134         int all = encode(cnt);
    135         int ret = -1;
    136         for(int i=0 ; i<ac.sz ; i++) ret = max(ret , dp[i][all]);
    137         printf("Case %d: %d
    " , ++cas , ret);
    138     }
    139     return 0;
    140 }
  • 相关阅读:
    正经学C#_循环[do while,while,for]:[c#入门经典]
    Vs 控件错位 右侧资源管理器文件夹点击也不管用,显示异常
    asp.net core 获取当前请求的url
    在实体对象中访问导航属性里的属性值出现异常“There is already an open DataReader associated with this Command which must be
    用orchard core和asp.net core 3.0 快速搭建博客,解决iis 部署https无法登录后台问题
    System.Data.Entity.Core.EntityCommandExecution The data reader is incompatible with the specified
    初探Java设计模式3:行为型模式(策略,观察者等)
    MySQL教程77-CROSS JOIN 交叉连接
    MySQL教程76-HAVING 过滤分组
    MySQL教程75-使用GROUP BY分组查询
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4749829.html
Copyright © 2011-2022 走看看