LCS最长公共子序列HDU1159

最近一直在学习算法,基本上都是在学习动态规划以及字符串。当然,两者交集最经典之一则是LCS问题。

首先LCS的问题基本上就是在字符串a,b之间找到最长的公共子序列,比如 YAOLONGBLOG 和 YCLPBPG,其最长公共子序列则是YLBG

当然当字符串比较大时候,枚举则略显困难。

首先我们先考虑求一个基本问题,就是LCS的长度。

很容易可以理解递推式: 

当a[i]==b[j],c[i][j]=c[i-1][j-1]+1;

当a[i]!=b[j], c[i][j]=max(c[i-1][j],c[i][j-1]);

对应HDU1159. 

Problem Description
A subsequence of a given sequence is the given sequence with some elements (possible none) left out. Given a sequence X = <x1, x2, ..., xm> another sequence Z = <z1, z2, ..., zk> is a subsequence of X if there exists a strictly increasing sequence <i1, i2, ..., ik> of indices of X such that for all j = 1,2,...,k, xij = zj. For example, Z = <a, b, f, c> is a subsequence of X = <a, b, c, f, b, c> with index sequence <1, 2, 4, 6>. Given two sequences X and Y the problem is to find the length of the maximum-length common subsequence of X and Y. 
The program input is from a text file. Each data set in the file contains two strings representing the given sequences. The sequences are separated by any number of white spaces. The input data are correct. For each set of data the program prints on the standard output the length of the maximum-length common subsequence from the beginning of a separate line. 
 

Sample Input
  
    
abcfbc abfcab programming contest abcd mnp
 

Sample Output
  
    
4 2 0
这就是裸题啦。利用上面的递推式很容易就写到一个简单的程序。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
#define MAX 1000
int c[MAX][MAX];

int LCS(string a,string b){
	int n=a.length();
	int m=b.length();
    memset(c,0,sizeof(c));
	int i,j;
	for(i=1;i<=n;i++)
		for(j=1;j<=m;j++){
			if(a[i-1]==b[j-1]){
			    c[i][j]=c[i-1][j-1]+1;
			}else {
				c[i][j]=c[i][j-1]>c[i-1][j]?c[i][j-1]:c[i-1][j];
			
			}
		}
		return c[n][m];

}
int main(){
	string a,b;
	while(cin>>a>>b){
	   
	  cout<<LCS(a,b)<<endl;
	}


	
	return 0;

}

不过为了体现CPP的模板作用,我还写了另外一个版本,不过没有写成HDU1159的题解,只是一个LCS的实现。


/*******************************************************************************/
/* OS           : 3.2.0-58-generic #88-Ubuntu SMP Tue Dec 3 UTC 2013 GNU/Linux
 * Compiler     : g++ (GCC)  4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)
 * Encoding     : UTF8
 * Date         : 2014-03-197
 * All Rights Reserved by yaolong.
*****************************************************************************/
/* Description: ***************************************************************
*****************************************************************************/
/* Analysis: ******************************************************************
*****************************************************************************/
/*****************************************************************************/


#include <iostream>
#include <string>
#include <cstring>
using namespace std;

int max(int a,int b){
  return a>b?a:b;
}
template<typename Iterator>
int * lcsLength(Iterator x,Iterator y,int m,int n){
    int *c=new int[(m+1)*(n+1)],i,j;
    for(i=1;i<=m;i++)
        c[i*(n+1)]=0;
    for(j=0;j<=n;j++)
        c[j]=0;
    for(i=1;i<=m;i++)
       for(j=1;j<=n;j++)
          if(*(x+i-1)==*(y+j-1))
             c[i*(n+1)+j]=c[(i-1)*(n+1)+j-1]+1;
          else c[i*(n+1)+j]=max(c[(i-1)*(n+1)+j],c[(i)*(n+1)+j-1]);
    return c;

}
template<typename Iterator>
void printLCS(int *c,int n,Iterator x,Iterator y,int i,int j){
    if(i==0||j==0) return;
    if( *(x+i-1)==*(y+j-1) ){
        printLCS(c,n,x,y,i-1,j-1);
        cout<<*(x+i-1);
    }else if(c[(i-1)*(n+1)+j]>=c[i*(n+1)+j-1])
          printLCS(c,n,x,y,i-1,j);
     else printLCS(c,n,x,y,i,j-1);


}
int main(){

    char *x="ACCGGTCGAGTGCGCGGAAGCCGGCCGAA",
         *y="GTCGTTCGGAATGCCGTTGCTCTGTAAA";
     int *c;
     int n=strlen(x),m=strlen(y);

     c=lcsLength(x,y,n,m);
     printLCS(c,m,x,y,n,m);
     cout<<endl<<c[ n*(m+1)+m]<<endl;
     delete []c;





     return 0;
}



你可能感兴趣的:(HDU)