题目大意:
调整基因的顺序,希望使得最后得到的基因包含有最多的匹配串基因,使得所能达到的智商最高
这里很明显要用状态压缩当前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\n" , ++cas , ret); 138 } 139 return 0; 140 }
我还在坚持,我还未达到我所想,梦~~一直在