最长公共子序列(lcs)是dp的一块重要内容,求两段字符串的最大公共长度。
如下是模板代码:
for (int i = 1; i <= str1.Length; i++)
for (int j = 1; j <= str2.Length; j++)
{
//相等的情况
if (str1[i - 1] == str2[j - 1])
martix[i, j] = martix[i - 1, j - 1] + 1;
else
{
//比较“左边”和“上边“,根据其max来填充
if (martix[i - 1, j] >= martix[i, j - 1])
martix[i, j] = martix[i - 1, j];
else
martix[i, j] = martix[i, j - 1];
}
}
poj1080
题目大意:给定t的案例。一个案例给定两个字符串的长度,和字符串,只含有’A‘C’G‘T’-‘五个字符。并且给出每两个字符所代表的数字。要求在不改变最大长度的情况下,求出两个字符串匹配之后的最大数。(可在较短字符串内添加字符‘-’)
思路如下:
字符串取str1[i] str2[j]时有以下三种情况
1:str1[i]~~'-' 即temp1=map[i-1][j]+data[str1[i]]['-']
2: ‘-’~~str2[j] 即temp2=map[i][j-1]+data[str2[j]]['-']
3: str1[i]~~str2[j] 即temp3=map[i][j]+data[str1[i-1]][str2[j-1]]
综上所述 map[i][j]=max(temp1,temp2,temp3)
此时,map[aa][bb]即为最大的数。
代码如下:
#include<stdio.h>
#include<string.h>
int map[105][105],aa,bb;
char a[105],b[105];
int data[10][10]={{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 get_id(char p) //得到每个字符对应的序号
{
switch(p)
{
case 'A': return 0;
case 'C': return 1;
case 'G': return 2;
case 'T': return 3;
case '-': return 4;
}
}
int MAX(int a,int b,int c) //取三个数中的最大数
{
int k;
k=a>b? a:b;
k=k>c? k:c;
return k;
}
void Work()
{
int i,j;
map[0][0]=0; //初始化
for(i=1;i<=aa;i++)
map[i][0]=data[get_id(a[i])][get_id('-')]+map[i-1][0];
for(j=1;j<=bb;j++)
map[0][j]=data[get_id(b[j])][get_id('-')]+map[0][j-1];
for(i=1;i<=aa;i++) //dp部分
for(j=1;j<=bb;j++)
{
int temp1=map[i-1][j-1]+data[get_id(a[i])][get_id(b[j])];
int temp2=map[i-1][j]+data[get_id(a[i])][get_id('-')];
int temp3=map[i][j-1]+data[get_id(b[j])][get_id('-')];
map[i][j]=MAX(temp1,temp2,temp3);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%s",&aa,a+1);
scanf("%d%s",&bb,b+1);
Work();
printf("%d\n",map[aa][bb]);
}
return 0;
}
#include<stdio.h>
#include<string.h>
int map[105][105],aa,bb;
char a[105],b[105];
int data[10][10]={{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 get_id(char p) //得到每个字符对应的序号
{
switch(p)
{
case 'A': return 0;
case 'C': return 1;
case 'G': return 2;
case 'T': return 3;
case '-': return 4;
}
}
int MAX(int a,int b,int c) //取三个数中的最大数
{
int k;
k=a>b? a:b;
k=k>c? k:c;
return k;
}
void Work()
{
int i,j;
map[0][0]=0; //初始化
for(i=1;i<=aa;i++)
map[i][0]=data[get_id(a[i])][get_id('-')]+map[i-1][0];
for(j=1;j<=bb;j++)
map[0][j]=data[get_id(b[j])][get_id('-')]+map[0][j-1];
for(i=1;i<=aa;i++) //dp部分
for(j=1;j<=bb;j++)
{
int temp1=map[i-1][j-1]+data[get_id(a[i])][get_id(b[j])];
int temp2=map[i-1][j]+data[get_id(a[i])][get_id('-')];
int temp3=map[i][j-1]+data[get_id(b[j])][get_id('-')];
map[i][j]=MAX(temp1,temp2,temp3);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d%s",&aa,a+1);
scanf("%d%s",&bb,b+1);
Work();
printf("%d\n",map[aa][bb]);
}
return 0;
}