• HDU3341 Lost's revenge(AC自动机+DP)


    题目是给一个DNA重新排列使其包含最多的数论基因。

    考虑到内存大概就只能这么表示状态:

    dp[i][A][C][G][T],表示包含各碱基个数为ACGT且当前后缀状态为自动机第i的结点的字符串最多的数论基因数

    其中ACGT可以hash成一个整数(a*C*G*T+c*G*T+g*T+T),这样用二维数组就行了,而第二维最多也就11*11*11*11个。

    接下来转移依然是我为人人型,我是丢进一个队列,用队列来更新状态的值。

    这题果然挺卡常数的,只好手写队列,最后4500msAC,还是差点超时,代码也搞得挺乱的。

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 int tn,ch[555][4],fail[555],flag[555];
     5 int idx[128];
     6 void insert(char *s){
     7     int x=0;
     8     for(int i=0; s[i]; ++i){
     9         int y=idx[s[i]];
    10         if(ch[x][y]==0) ch[x][y]=++tn;
    11         x=ch[x][y];
    12     }
    13     ++flag[x];
    14 }
    15 int que[555];
    16 void init(){
    17     memset(fail,0,sizeof(fail));
    18     int front=0,rear=0;
    19     for(int i=0; i<4; ++i){
    20         if(ch[0][i]) que[rear++]=ch[0][i];
    21     }
    22     while(front!=rear){
    23         int x=que[front++];
    24         for(int i=0; i<4; ++i){
    25             if(ch[x][i]) que[rear++]=ch[x][i],fail[ch[x][i]]=ch[fail[x]][i],flag[ch[x][i]]+=flag[ch[fail[x]][i]];
    26             else ch[x][i]=ch[fail[x]][i];
    27         }
    28     }
    29 }
    30 int d[555][14641];
    31 int quex[555*14641],quey[555*14641];
    32 int main(){
    33     idx['A']=0; idx['C']=1; idx['G']=2; idx['T']=3;
    34     char str[44];
    35     int n,cse=0;
    36     while(~scanf("%d",&n) && n){
    37         tn=0;
    38         memset(ch,0,sizeof(ch));
    39         memset(flag,0,sizeof(flag));
    40         while(n--){
    41             scanf("%s",str);
    42             insert(str);
    43         }
    44         init();
    45         scanf("%s",str);
    46         int times[4]={0};
    47         for(int i=0; str[i]; ++i){
    48             ++times[idx[str[i]]];
    49         }
    50         int tcal0=(times[1]+1)*(times[2]+1)*(times[3]+1);
    51         int tcal1=(times[2]+1)*(times[3]+1);
    52         int tcal2=(times[3]+1);
    53         memset(d,-1,sizeof(d));
    54         d[0][0]=0;
    55         int front=0,rear=0,x,y,ny,cnt[4];
    56         quex[rear]=0; quey[rear]=0; ++rear;
    57         while(front!=rear){
    58             x=quex[front]; y=quey[front]; ++front;
    59             ny=y;
    60             cnt[0]=ny/tcal0;
    61             ny-=cnt[0]*tcal0;
    62             cnt[1]=ny/tcal1;
    63             ny-=cnt[1]*tcal1;
    64             cnt[2]=ny/tcal2;
    65             cnt[3]=ny-cnt[2]*tcal2;
    66             for(int i=0; i<4; ++i){
    67                 if(cnt[i]>=times[i]) continue;
    68                 ++cnt[i];
    69                 ny=cnt[0]*tcal0+cnt[1]*tcal1+cnt[2]*tcal2+cnt[3];
    70                 if(d[ch[x][i]][ny]==-1){
    71                     d[ch[x][i]][ny]=d[x][y]+flag[ch[x][i]];
    72                     quex[rear]=ch[x][i]; quey[rear]=ny; ++rear;
    73                 }else if(d[ch[x][i]][ny]<d[x][y]+flag[ch[x][i]]){
    74                     d[ch[x][i]][ny]=d[x][y]+flag[ch[x][i]];
    75                 }
    76                 --cnt[i];
    77             }
    78         }
    79         y=times[0]*tcal0+times[1]*tcal1+times[2]*tcal2+times[3];
    80         int res=0;
    81         for(int x=0; x<=tn; ++x){
    82             if(res<d[x][y]) res=d[x][y];
    83         }
    84         printf("Case %d: %d
    ",++cse,res);
    85     }
    86     return 0;
    87 }
  • 相关阅读:
    [Leetcode][动态规划] 零钱兑换
    [Linux][函数]flock函数的用法
    [Leetcode][动态规划] 买卖股票的最佳时机IV
    [C++] 类的设计(2)——拷贝控制(1)
    [C++] C++中的常用库
    Python 爬虫学习笔记2
    Python 爬虫学习笔记1
    Tableau学习笔记:join
    可视化文摘:multifaceted data and story
    可视化学习笔记8:一般设计技巧
  • 原文地址:https://www.cnblogs.com/WABoss/p/5173783.html
Copyright © 2020-2023  润新知