• 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 }
  • 相关阅读:
    html5-特殊符号的使用
    html5-表格
    html5-列表
    html5-绝对路径/相对路径
    html5-嵌入图片
    html5-超级链接
    html5-常用的文本元素
    html5-了解元素的属性
    Scanner类throwFor(Unknown Source)及跳过下一个扫描器分析
    有关HashMap的一些问题及解答
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/4749829.html
Copyright © 2020-2023  润新知