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\n",++cse,res);
85     }
86     return 0;
87 }

 

你可能感兴趣的:(HDU3341 Lost's revenge(AC自动机+DP))