动态规划-最长公共子序列与最长公共子串

1.最长公共子序列

参考博客:

http://blog.csdn.net/hrn1216/article/details/51534607

http://blog.csdn.net/u013074465/article/details/45392687

代码:

#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>


#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 101
#define MAX 1<<30
#define V vector<int>

using namespace std;

int a[LEN],b[LEN]; 
int dp[LEN][LEN];
int N,M;
vector<vector<int> > ans;

void printDP(){
    int i,j;
    F(i,1,N+1){
        F(j,1,M+1){
            O("%d\t",dp[i][j]);
        }
        OL("\n");
    }
}

void buildLCS(int x,int y,V vec){
    while(x>0 && y>0){
        if(a[x]==b[y]){
            vec.push_back(a[x]);
            x--;y--;
        }else{
            if(dp[x-1][y]>dp[x][y-1]){
                x--;
            }else if(dp[x-1][y]<dp[x][y-1]){
                y--;
            }else{
                buildLCS(x,y-1,vec);
                x--;
            }
        }
    }
    int i=vec.size()-1;
    while(i>=0){
        O("%d ",vec[i]);
        i--;
    }
    OL("");
}

int main(){
    freopen("LCS.txt","r",stdin);
    int i,j;
    scanf("%d",&N);
    F(i,1,N+1) I("%d",&a[i]);
    scanf("%d",&M);
    F(i,1,M+1) I("%d",&b[i]);
    F(i,1,N+1){ 
        F(j,1,M+1){
            if(a[i]==b[j])
                dp[i][j]=dp[i-1][j-1]+1;
            else
                dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
        }
    }
    printDP();
    O("最长公共子序列长度: %d\n",dp[N][M]);
    V vec;
    buildLCS(N,M,vec);
    return 0;
}
View Code

测试数据:

9
3 5 7 4 8 6 7 8 2
8
1 3 4 5 6 7 7 8

 


2.最长公共子串

代码:

#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>


#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 101
#define MAX 1<<30
#define V vector<int>

using namespace std;

int a[LEN],b[LEN]; 
int dp[LEN][LEN];
int N,M;
vector<vector<int> > ans;

void printDP(){
    int i,j;
    F(i,1,N+1){
        F(j,1,M+1){
            O("%d\t",dp[i][j]);
        }
        OL("\n");
    }
}

int main(){
    freopen("最长公共子串.txt","r",stdin);
    int i,j;
    scanf("%d",&N);
    F(i,1,N+1) I("%d",&a[i]);
    scanf("%d",&M);
    F(i,1,M+1) I("%d",&b[i]);
    int mx,my,mlen=0;
    F(i,1,N+1){ 
        F(j,1,M+1){
            if(a[i]==b[j]){
                dp[i][j]=dp[i-1][j-1]+1;
                if(mlen<dp[i][j]){
                    mlen=dp[i][j];
                    mx=i;
                    my=j;
                }
            }
            else
                dp[i][j]=0;
        }
    }
    printDP();
    O("最长公共子序列长度: %d\n",mlen);
    V ans;
    while(dp[mx][my]){
        ans.insert(ans.begin(),a[mx]);
        mx--;my--;
    }
    FF(i,ans.size()){
        printf("%d ",ans[i]);
    }
    return 0;
}
View Code

测试数据:

9
3 5 7 4 8 6 7 8 2
8
1 3 4 8 6 7 7 8

 


 

3.相似基因

代码:

#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>


#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 110
#define MAX 1<<30
#define V vector<int>

using namespace std;


int dp[LEN][LEN];
int mat[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 to(char ch){
    if(ch=='A') return 0;
    else if(ch=='C') return 1;
    else if(ch=='G') return 2;
    else if(ch=='T') return 3;
    else return 4;
}

int main(){
//    freopen("相似基因.txt","r",stdin);
    int an,bn,i,j;
    char buf[LEN];
    string a,b;
    I("%d",&an);
    I("%s",buf);
    a=buf;
    a.insert(0,"#");
    I("%d",&bn);
    I("%s",buf);
    b=buf;
    b.insert(0,"#");
    memset(dp,-127,sizeof(dp));
    dp[0][0]=0;
    for(i=0;i<=an;i++){
        for(j=0;j<=bn;j++){
            if(i && j) dp[i][j]=max(dp[i][j],dp[i-1][j-1] + mat[to(a[i])][to(b[j])]  );
            if(i) dp[i][j]=max(dp[i][j],dp[i-1][j] + mat[to(a[i])][4]  );
            if(j) dp[i][j]=max(dp[i][j],dp[i][j-1] + mat[4][to(b[j])]  );    
        }
    }
    printf("%d",dp[an][bn]);
    return 0;
}
View Code

理解: 在边界条件的限制下,有三种情况:

1. 当前基因与对象基因进行匹配,        =dp[i-1][j-1]+f(i,j)

2. 当前基因放弃匹配,插入一个“-”(空符号)   =dp[i-1][j]+f(i,∅)

3. 对象基因放弃匹配,插入一个“-”(空符号)   =dp[i][j-1]+f(∅,j)

基本思路与LCS相同

 


 

posted @ 2018-02-07 18:03  TQCAI  阅读(217)  评论(0编辑  收藏  举报