DNA
Time Limit:5000MS Memory Limit:65536K
Total Submit:65 Accepted:5
Description
DNA能够表达数以百万计的基因密码,所用的仅仅是4种分子。我们分别用A、G、T和C表示这4种分子。一条基因就是DNA链上的一个由这4种分子组成的片段。人体按照一条基因上的分子序列可以合成出一种蛋白质。一条基因片段对应着一种蛋白质。
现在给定每种基因能合成出来的蛋白质的分数。但是,在蛋白质合成时,同一条DNA链可以用不同的方式解释出不同的基因片段。比如说,一条DNA链AATGCGG,可以解释出AATG 和 GG 这两个基因片段,也可以解释出AT 和 GCCG这两个基因片段。在同一种解释中,不得出现重叠的片段。你的任务是,仔细安排一条DNA链上的基因,让它能合成出来的蛋白质的分数总和最大。
Input
输入多个测试用例。每个测试用例的第一行是一个整数N(1 < N ≤ 100,000);接下来有N行,每行包括一个长度不超过10的表示基因片段的串S和一个整数C(按照基因片段S合成的蛋白质的分数);每个测试用例的最后一行是长度不超过1000的串(一条DNA链)。
Output
按照输出样例的格式输出每个测试用例的DNA链能合成的蛋白质的分数总和的最大值。
Sample Input
4
AATG 3
AT 2
GCGG 3
GG 2
AATGCGG
3
A 1
C 1
G 1
T
字典树+DP
#include<iostream> using namespace std; #define N 100009 char input[1024],buff[1024]; int dp[1009]; int max(int a,int b){ return a>b?a:b;} struct t_node { bool f; int len,val; int next[26]; void init(){ f=0; memset(next,-1,sizeof(next)); } }trie[N*3]; int p; void root () { trie[p=0].init(); } void insert(char *a,int val) { int index=0; int len=strlen(a); int cur,i; for(i=len-1;i>=0;i--) { cur=a[i]-'A'; if(trie[index].next[cur]==-1) { trie[++p].init(); trie[index].next[cur]=p; } index=trie[index].next[cur]; } trie[index].f=1; trie[index].len=len; trie[index].val=val; } int find(char *a,int k) { int index=0,i,cur; int len=strlen(a); for(i=len-1;i>=0;i--) { cur=a[i]-'A'; if(trie[index].next[cur]==-1) return 0; index=trie[index].next[cur]; if(trie[index].f==1) { dp[k+1]=max(dp[k+1],dp[k+1-trie[index].len]+trie[index].val); } } return 0; } int main() { int n,i,k=0; int len,val; while(scanf("%d",&n)!=EOF) { root(); for(i=0;i<n;i++) { scanf("%s%d",buff,&val); insert(buff,val); } scanf("%s",input); len=strlen(input); memset(dp,0,sizeof(dp)); for(i=0;i<len;i++) { dp[i+1]=dp[i]; strncpy(buff,input,i+1); buff[i+1]='\0'; // printf("%s\n",buff); find(buff,i); // printf("%d\n",dp[i]); } printf("Case %d: ",++k); printf("%d\n",dp[len]); } return 0; }