序列比较问题在生物中有很多的应用
问题描述:把一个序列变成另一个序列的最少修改步数。用到动态规划
令A=a1,a2,a3,....an ,B=b1,b2,.....bm是2个字符串,其中字符取自一个有限集合(如英语字母表)。我们想一一改变A的字符变把A变成B.改变有3种
1)插入,把某个字符串插入到字符串
2)删除,从字符串中删除某个字符
3)替换,把字符串中的某个字符替换成另一字符
用A(i)表示a1,a2,a3......ai ; B(i)表示b1,b2.....bi
C(i,j)表示从A(i)变换到B(j)的最小的操作次数
现在要求的是C(n,m)即把A(n)变换到B(m)的最小次数
小于(n,m)的意思是“至少有一个小于其上界且另一个值不大于其上界的所有这样的(i,j)组合”
归纳假设:知道如何求解小于(n,m)问题C(i,j)(0<=i<=n,0<=j<=m)
现在如何是使得A(n)------>B(m)修改的次数最小
有三种选择:
a、删除A[n]能使得次数最少 则C(n,m)=A(n-1,m)+1
b、插入一个元素等于T[m]次数最少 则C(n,m)=C(n,m-1)+1
c 替换的时候 如果C[m]=A[n] 此时C(n,m)=C(n-1,m-1)
否则 C(n,m)=C(n-1,m-1)+1;
基础的情况的时候,C[0][j]=j(0<j<=m)
C[i][0]=i(0<i<=n)
基础情况 C(0,j)=i(0<=j<=m) C(i,0)=i(0<=i<=n)
如果要保存修改最后一次的变化
//1---delete A[n]
//2--->插入一个B[m];3----替换(没有代价的),没有变化
//4----替换 A[n]被替换为B[m]
// 序列比对.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
/*动态规划解决序列比较问题
author:surpassgood
问题描述:假设串S[1....n]可以进行删除,插入,替换操作,最后变成
T[1.....m],操作次数假设C(n,m)
怎么样解决使得操作的次数最小
假设 a、删除S[n]能使得次数最少 则C(n,m)=c(n-1,m)+1
b、插入一个元素等于T[m]次数最少 则C(n,m)=c(n,m-1)+1
c 替换的时候 如果C[m]=T[n] 此时C(n,m)=c(n-1,m-1)
否则 C(n,m)=C(n-1,m-1)+1;
基础的情况的时候,C[0][j]=j(0<j<=m)
C[i][0]=i(0<i<=n)
*/
#define N 10
#define M 10
int C[N+1][M+1];
char S[]=" abbc",T[]=" babb";
int modify[N+1][M+1];//1---delete s[n]
//2--->插入一个T[m];3----替换(没有代价的),没有变化
//4----替换 S[n]被替换为T[m]
void prin(int modify[][M+1],int n,int m);//打印做S[n]做了哪些操作
int min1(int x,int y)
{
return x<y?x:y;
}
int fun(char *S,char *T,int n,int m)//下标从1开始的
{
int i,j;
int x,y,z,w,min=0xffff;//x删除的时候 y插入 z替换的时候 w不变化的时候
//最小值
int opere;
for(i=1;i<=n;i++)
{
for(j=1;j<=m;j++)
{
/*相应的元素赋值*/
x=C[i-1][j]+1;
y=C[i][j-1]+1;
if(min1(x,y)==x)
{
min=x;
opere=1;
}else
{
min=y;
opere=2;
}
if(S[i]==T[j])
{
w=C[i-1][j-1];
if(min>w)
{
min=w;
opere=3;
}
}else
{
z=C[i-1][j-1]+1;
if(min>z)
{
min=z;
opere=4;
}
}
C[i][j]=min;
modify[i][j]=opere;
min=0xffff;
opere=0;
}
}
prin(C,n,m);
cout<<endl;
return C[n][m];
}
void prin(int C[][M+1],int n,int m)//打印做S[n]做了哪些操作
{
if(n<0||m<0) return;
if(m==0&&n==0) return;
//1---delete s[n]
//2--->插入一个T[m];3----替换(没有代价的),没有变化
//4----替换 S[n]被替换为T[m]
switch (modify[n][m])
{
case 1 :
{prin(C,n-1,m);
cout<<"delete "<<S[n]<<endl;break;}
case 2:
{
cout<<S[n]<<"--insert-- "<<T[m]<<endl;
prin(C,n,m-1);
break;
}
case 4:
{
cout<<S[n]<<"被换成"<<T[m]<<endl;
prin(C,n-1,m-1);
break;
}
case 3:
prin(C,n-1,m-1);break;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int i,j;
for(i=0;i<=N;i++)
for(j=0;j<=M;j++)
modify[i][j]=0;
for(i=0;i<=N;i++)
{
C[i][0]=i;
modify[i][0]=1;//这要注意了,我当时赋值为2 ,发现结果不对,1表示删除
}
for(j=0;j<=N;j++)
{
C[0][j]=j;
modify[0][j]=2;
}
//cout<<fun(S,T,4,4)<<endl;
cout<<"input the source string 小标从1开始,在你要输入的字符串前加个字符"<<endl;
cin>>S;
cout<<"input the destination string 小标从1开始"<<endl;
cin>>T;
cout<<"source---->"<<endl;
for(i=1;i<strlen(S);i++)
{
cout<<S[i];
}
cout<<endl;
cout<<"-----covert-------"<<endl<<endl;
cout<<"变化了次数:"<<fun(S,T,strlen(S)-1,strlen(T)-1)<<endl;
cout<<"-----end-------"<<endl<<endl;
cout<<"destination---->"<<endl;
for(i=1;i<strlen(T);i++)
{
cout<<T[i];
}
cout<<endl;
return 0;
}