hdu1080 DP(类最长公共子序列)

题意,有两个字符串,分别由四个字母构成,字母之间有不同的相似度,允许在两个字符串都按原顺序排列的情况下进行字母与字母之间的匹配,也可以让字母与空格匹配,即相当于在字符串中间加空格来一一匹配,每个字母与空格也有相应的相似度,但空格不能和空格匹配。问当给出两个字符串时,求它们的最大相似度。

我一开始的想法也是想类似于最长公共子序列的做法,只是将匹配数变成了一个权值,总的相似度。这个方向是正确的,但是我却在细节上犯了糊涂,我一直在考虑当第一条链的第 i 个和第二条的第 j 个相匹配,这样的情况,从前面的各种情况转移到这里。但事实上,其实原本就该想到,最长公共子序列的状态转移也是对于匹配完第一条的第 i 个和第二条的第 j 个,而不是这两个恰好匹配。这样做反而容易进行状态转移。

状态转移关系如下:

dp [ i ] [ j ] 表示匹配完第一条的第 i 个和第二条的第 j 个(均可以与空格进行匹配);

① dp [ i - 1 ] [ j ] + v (第一条第 i 个与空格匹配后增加的相似度) ,当该值大于 dp 原值时就用它优化 dp;

② dp [ i ] [ j - 1 ] + v (第二条第 j 个与空格匹配后增加的相似度) ,当该值大于 dp 原值时就用它优化 dp;

③ dp [ i - 1 ] [ j - 1 ] + v(第一条第 i 个与第二条第 j 个匹配后增加的相似度) ,当该值大于 dp 原值时就用它优化 dp;

这样就行了;

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #define max(a,b) a>b?a:b
 5 #define INF 100000
 6 using namespace std;
 7 int v[5][5]={{0,-3,-4,-2,-1},{-3,5,-1,-2,-1},{-4,-1,5,-3,-2},{-2,-2,-3,5,-2},{-1,-1,-2,-2,5}};
 8 int dp[105][105];
 9 int s1[105],s2[1059];
10
11 int main(){
12     int n;
13     while(scanf("%d",&n)!=EOF){
14         for(int q=1;q<=n;q++){
15             memset(s1,0,sizeof(s1));
16             memset(s2,0,sizeof(s2));
17             int l1,l2;
18             scanf("%d",&l1);
19             int i,j;
20             getchar();
21             char a;
22             dp[0][0]=0;
23             for(i=1;i<=l1;i++){
24                 a=getchar();
25                 if(a==‘A‘) s1[i]=1;
26                 else if(a==‘C‘) s1[i]=2;
27                 else if(a==‘G‘) s1[i]=3;
28                 else if(a==‘T‘) s1[i]=4;
29                 dp[i][0]=dp[i-1][0]+v[s1[i]][0];
30             }
31             scanf("%d",&l2);
32             getchar();
33             for(i=1;i<=l2;i++){
34                 a=getchar();
35                 if(a==‘A‘) s2[i]=1;
36                 else if(a==‘C‘) s2[i]=2;
37                 else if(a==‘G‘) s2[i]=3;
38                 else if(a==‘T‘) s2[i]=4;
39                 dp[0][i]=dp[0][i-1]+v[0][s2[i]];
40             }
41             int k;
42 /*
43             printf("s1:");
44             for(i=1;i<=l1;i++)printf("%d",s1[i]);
45             printf("\n");
46             printf("s2:");
47             for(i=1;i<=l2;i++)printf("%d",s2[i]);
48             printf("\n");
49 */
50             for(i=1;i<=l1;i++){
51                 for(j=1;j<=l2;j++){
52                     dp[i][j]=-INF;
53                     dp[i][j]=max(dp[i][j],dp[i-1][j]+v[s1[i]][0]);
54                     dp[i][j]=max(dp[i][j],dp[i][j-1]+v[0][s2[j]]);
55                     dp[i][j]=max(dp[i][j],dp[i-1][j-1]+v[s1[i]][s2[j]]);
56                 }
57             }
58             printf("%d\n",dp[l1][l2]);
59         }
60     }
61     return 0;
62 }

时间: 2024-10-23 16:29:23

hdu1080 DP(类最长公共子序列)的相关文章

hdu1243 dp (类最长公共子序列)

题意:射击演习中,已知敌人出现的种类顺序,以及自己的子弹种类顺序,当同种类的子弹打到同种类的敌人时会得到相应分数,问最多能得多少分. 这题的题意很好理解,而且模型也很常见,是带权值的类最长公共子序列问题.但是我 WA 了四发```第一发,t 定义了两次,并执意要从下标 1 开始读(这个貌似没问题的).第二次是改了之后 dp 数组的转移方程没有写对.第三 WA 是改了转移方程还是没有改对Orz ,第四 WA 是```我的内心几乎是崩溃的,恩,还是没有改对…… 1 #include<stdio.h>

UVA 10100- Longest Match(dp之最长公共子序列)

题目地址:UVA 10100 题意:求两组字符串中最大的按顺序出现的相同单词数目. 思路:将字串中的连续的字母认作一个单词,依次计算出两个字符串中的单词,其中第1个字符串的单词序列为t1.word[1]-..t1.word[n],第2个字符串的单词序列为t2.word[1]-..t2.word[m].然后将每个单词当成一个字符,使用LCS算法计算出两个字符串的最长公共子序列,该序列的长度就是最长匹配. #include <stdio.h> #include <math.h> #in

dp之最长公共子序列

例1:给你两个字符串,找出最长子序列的长度. 对于字符串t, 字符串s,给定特定的i, j代表t,s的位置,只存在三种情况: 1. i == 0 ||  j==0, M[i][j] = 0; 2. t[i] == s[j], M[i][j] = min(M[j-1][j-1] + 1, M[i-1][j], M[i][j-1]);//.....不知道怎么解释.... 3. t[i] != s[j] , M[i][j] = min(M[i-1][j], M[i][j-1]);//..... 经典d

【DP】最长公共子序列

Description 字符序列的子序列是指从给定字符序列中随意地(不一定连续)去掉若干个字符(可能一个也不去掉)后所形成的字符序列.令给定的字符序列X="x0,x1,-,xm-1",序列Y="y0,y1,-,yk-1"是X的子序列,存在X的一个严格递增下标序列<i0,i1,-,ik-1>,使得对所有的j=0,1,-,k-1,有xij = yj.例如,X="ABCBDAB",Y="BCDB"是X的一个子序列. 对给

(hdu step 3.2.2)Common Subsequence(简单dp:求最长公共子序列的长度)

在写题解之前给自己打一下广告哈~..抱歉了,希望大家多多支持我在CSDN的视频课程,地址如下: http://edu.csdn.net/course/detail/209 题目: Common Subsequence Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 976 Accepted Submission(s): 538   Probl

hdu1159-Common Subsequence(DP:最长公共子序列LCS)

Common Subsequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 49216    Accepted Submission(s): 22664 Problem Description A subsequence of a given sequence is the given sequence with some el

[dp]LCS最长公共子序列

https://www.51nod.com/tutorial/course.html#!courseId=4 复杂度:${\rm O}(nm)$ 转移方程: 1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 int n,m; 5 int dp[1002][1002]; 6 char path[1002]; 7 string s,t; 8 int main(){ 9 cin>>s>

Codeforcs 1114D Flood Fill (区间DP or 最长公共子序列)

题意:给你n个颜色块,颜色相同并且相邻的颜色块是互相连通的(连通块).你可以改变其中的某个颜色块的颜色,不过每次改变会把它所在的连通块的颜色也改变,问最少需要多少次操作,使得n个颜色块的颜色相同. 例如:[1, 2, 2, 3, 2]需要2步:[1, 2, 2, 3, 2] -> [1, 2, 2, 2, 2] -> [2, 2, 2, 2, 2]. 思路:我们先把颜色块压缩(即把本来颜色相同并且相邻的颜色块合并).容易发现,如果出现了形如[1, 2, 3, 1]这种情况, 那么显然先合并两个

一天一道算法题(4)---最长公共子序列

题目 给定两个字符串str1和str2,返回两个字符串的最长公共子序列 解析 本题是非常经典的动态规划问题,先来介绍求解动态规划表的过程.如果str1的长度为M,str2的长度为N,生成大小为M*N的矩阵dp,行数为M,列数为N.dp[i][j]的含义是str1[0..i]和str2[0..j]的最长公共子序列的长度.从左到右,再从上到下计算矩阵dp. 1.矩阵dp第一列即dp[0..M-1][0],dp[i][0]的含义是str1[0..i]与str2[0]的最长公共子序列的长度. 2.矩阵d