最长公共子序列 HDU 1159/1080/1503
来源:互联网 发布:mac更新后部分变英文 编辑:程序博客网 时间:2024/06/01 07:24
hdu 1159
题意:求两个串的最长公共子序列
#include<iostream>#include<string.h>#include<stdio.h>#define size 1000using namespace std;char str1[size],str2[size];int dp[size][size];int main(){ int len1,len2; while(scanf("%s",str1)!=EOF) { getchar(); scanf("%s",str2); len1=strlen(str1); len2=strlen(str2); memset(dp,0,sizeof(dp)); for(int i=1;i<=len1;i++) { for(int j=1;j<=len2;j++) { if(str1[i-1]==str2[j-1] ) { dp[i][j]=dp[i-1][j-1]+1; } else { dp[i][j]= max(dp[i-1][j],dp[i][j-1]); } } } printf("%d\n",dp[len1][len2]); } return 0;}hdu 1080
题意:两个字符串,每个字符串中都可以插入'-',保证最后两串的长度相等,之后让两串对齐,两串相同位置的字母组成的字符匹配有一个值,问这些值的和最大是多少
#include<iostream>#include<string.h>#include<stdio.h>#define INF 0x3fffffffusing namespace std;int tmp[5][5]={ {5,-1,-2,-1,-3}, {-1,5,-3,-2,-4}, {-2,-3,5,-2,-2}, {-1,-2,-2,5,-1}, {-3,-4,-2,-1,0}};int tt(char c){ if(c=='A') return 0; else if(c=='C') return 1; else if(c=='G') return 2; else return 3;}int dp[110][110];int main(){ int len1,len2; char str[110]; int a[110],b[110]; int T; scanf("%d",&T); while(T--) { scanf("%d %s",&len1,str); int i,j; for(i=0;i<len1;i++) a[i]=tt(str[i]); scanf("%d %s",&len2,str); for(i=0;i<len2;i++) b[i]=tt(str[i]);// for(i=0;i<len1;i++) cout<<a[i]<<" ";cout<<endl;// for(i=0;i<len2;i++) cout<<b[i]<<" ";cout<<endl; for(i=0;i<=len1;i++) //给dp初始化的原因是tmp[][]中包含负数,且结果是取最大值,所以显然不能直接初始化为0 { for(j=0;j<=len2;j++) dp[i][j]=-INF; } dp[0][0]=0; //为下面的边界初始化有效 //如果str1的前i个字符都不能与str2中合理匹配,则它们与'_'相匹配,而“匹配值”逐次累加。 for(i=1;i<=len1;i++) dp[i][0]=dp[i-1][0]+tmp[a[i-1]][4]; //之前这里写成了dp[][]+=tmp[][] for(j=1;j<=len2;j++) dp[0][j]=dp[0][j-1]+tmp[4][b[j-1]]; //dp[i][j]代表str1前i-1个与str2前j-1个“匹配值”的和。 for(i=1;i<=len1;i++) { for(j=1;j<=len2;j++) { dp[i][j]=max(dp[i][j],//不可去除,可能是上面的边界情况 max(dp[i-1][j-1]+tmp[a[i-1]][b[j-1]],//若str1[i-1]==str[j-1] max(dp[i-1][j]+tmp[a[i-1]][4],//可能str1[i-1]与'—'匹配,结果最大 dp[i][j-1]+tmp[4][b[j-1]])));//可能str2[j-1]与'-'匹配结果最大 } } printf("%d\n",dp[len1][len2]); } return 0;}
hdu 1503
题意:
给你两个单词,然后你要把两个单词拼接成一个新单词,使得新单词的子序列中包含两个单词,并且要使这个新单词最短
基本思路:
求最长公共子序列,令这个序列只输出一次就可以使新单词最短
记录路径:
增加二维数组road记录状态转移路径
road[i][j] = 0 表示road[i][j]由road[i-1][j-1]转移过来,即a[i-1]与b[j-1]属于最长公共子序列中的元素,扫描路径时将hash[i-1]赋值为j-1表示a串的i-1匹配b串的j-1【其中hash初始时全为-1】
road[i][j] = 1 表示road[i][j]由road[i-1][j]转移过来
road[i][j] = 2 表示road[i][j]由road[i][j-1]转移过来
输出答案:
先设置start变量【表示b串的当前位置】,扫描a串
①当对于a[i]有hash[i]==-1,说明a[i]不是最长公共子序列中的元素,直接输出并且continue;
②否则b串输出从start到hash[i]的值,因为a[i]跟b[hash[i]]匹配嘛,所以输出b[hash[i]]就不用输出a[i]勒,然后start变为hash[i] + 1;
#include<iostream>#include<string.h>#include<stdio.h>using namespace std;int main(){ char str1[110],str2[110]; int hash[110]; int dp[110][110]; int roat[110][110]; int len1,len2; int i,j; while(scanf("%s %s",str1,str2)!=EOF) { memset(dp,0,sizeof(dp)); memset(hash,-1,sizeof(hash)); memset(roat,-1,sizeof(roat)); len1=strlen(str1); len2=strlen(str2); for(i=1;i<=len1;i++) { for(j=1;j<=len2;j++) { if(str1[i-1]==str2[j-1]) { dp[i][j]=dp[i-1][j-1]+1; roat[i][j]=0; //cout<<"**********"<<endl; } else { if(dp[i-1][j]<dp[i][j-1]) { dp[i][j]=dp[i][j-1]; roat[i][j]=1; } else { dp[i][j]=dp[i-1][j]; roat[i][j]=2; } } } } //由roat[][]数组找路径,=0表示由[i-1][j-1]转换来(str1[i-1]=str2[j-1]) //=1 =2由上可推得 i=len1;j=len2; while(roat[i][j]!=-1) { if(roat[i][j]==0) { i--;j--; hash[i]=j; } else if(roat[i][j]==1) j--; else i--; } // for(int i=1;i<=len1;i++) cout<<"hash["<<i-1<<"]= "<<hash[i-1]<<endl; //输出组合词 int s=0; for(i=0;i<len1;i++) { while(hash[i]!=-1 && i<len1) { for(;s<=hash[i];s++) { printf("%c",str2[s]); } i++; } if(hash[i]==-1 && i<len1) printf("%c",str1[i]); } for(;s<len2;s++) { printf("%c",str2[s]); } printf("\n"); } return 0;}
- 最长公共子序列 HDU 1159/1080/1503
- hdu 1503 最长公共子序列
- hdu 1503 最长公共子序列变型
- hdu 1159 (最长公共子序列)
- hdu 1159 最长公共子序列
- HDU 1159 最长公共子序列
- HDU 1159 最长公共子序列
- hdu 1159 最长公共子序列
- HDU 1159 最长公共子序列
- HDU-1159(DP_最长公共子序列)
- hdu 1159 最长公共子序列
- HDU 1159 最长公共子序列
- hdu 1159 最长公共子序列
- hdu 1159 最长公共子序列
- HDU 1159(最长公共子序列)
- hdu 1159 最长公共子序列问题
- hdu 1159(最长公共子序列)
- hdu 1159(最长公共子序列)
- 文本比较算法Ⅱ——Needleman/Wunsch算法
- 二叉树的建立和中序、先序、后序遍历
- 通过myeclipse启动tomcat
- error和exception有什么区别
- 求1000以内偶数的和
- 最长公共子序列 HDU 1159/1080/1503
- POJ 2115
- ImageButton组件的应用(更改头像)
- 知易游戏开发教程cocos2d-x移植版002(上)
- c#TCP传输大文件
- linux内存管理之全局框架
- 单线程套间和多线程套间
- 配不上你的梦想
- 文本比较算法Ⅲ——计算文本的相似度