• 字符串的最长公共子序列问题


    // 最长公共子序列问题.cpp : Defines the entry point for the console application.
    //
    /*问题:给出两个字符串,找出它们的最长公共子序列
    什么是最长公共子序列?
    最长公共子序列,英文缩写为LCS(Longest Common Subsequence)。
    其定义是,一个序列 S ,如果分别是两个或多个已知序列的子序列,
    且是所有符合此条件序列中最长的,则 S 称为已知序列的最长公共子序列。
    而最长公共子串(要求连续)和最长公共子序列是不同的(可以是不连续的)
    例如:
    abgfjlmnp
    -  - - -
    afkqln
    --  --
    它们的最长公共子序列是:afln
    思路:
    利用动态规划方法
    设两个子序列X={x1,x2,x3,...xi},Y={y1,y2,y3,...,yi}
    设C[i,j]用来保存Xi和Yj的LCS长度(i=0,1...  j=0,1,...)
    可以得到递推方程:
    	 	     __
    	       _|   0 			   i=0 or j=0
        C[i,j]=|_   C[i-1,j-1]+1		   i,j>0 and xi=yi
    	       |__ max{C[i,j-1],C[i-1,j]}  i,j>0 and xi!=yi
    
     根据公式可以得知C[i,j]保存当前(Xi,Yi)的最大子序列长度
     知道了最长公共子序列的长度,下一步就是考虑如何输出这个序列
     为了输出子序列我们需要增加一个数组pos[i,j]
     pos[i,j]用来保存C[i,j]的解是由哪一个子问题的解得到的
     有三种情况:
     1:
     c[i,j]:=c[i-1,j-1]+1;  
     pos[i,j]:="↖"; 
     2:
     c[i,j]:=c[i-1,j];  
     pos[i,j]:="↑";  
     3:
     c[i,j]:=c[i,j-1];  
     pos[i,j]:="←"  
     构造子序列时:
     从pos[m,n]开始向前扫描:
     1.当pos[i,j]中遇到"↖"时(意味着xi=yi是LCS的一个元素),
     表示Xi与Yj的最长公共子序列是由Xi-1与Yj-1的最长公共子序列在尾部加上xi得到的子序列;
     2.当pos[i,j]中遇到"↑"时,表示Xi与Yj的最长公共子序列和Xi-1与Yj的最长公共子序列相同;
     3.当pos[i,j]中遇到"←"时,表示Xi与Yj的最长公共子序列和Xi与Yj-1的最长公共子序列相同。
     	    
    */
    #include "stdafx.h"
    #include <iostream>
    using namespace std;
    void ConstructLCS(int **pos,const char *str,int length1,int length2);
    void LCS(const char* str1,const char* str2,int length1,int length2)
    {
    	//初始化工作,动态创建两个二维数组
    	int **c=new int *[length1+1];
    	int **pos=new int *[length1+1];
    	for(int i=0;i<length1+1;i++)
    	{
    		c[i]=new int[length2+1];
    		pos[i]=new int[length2+1];
    	}
    	for(int i=0;i<length1+1;i++)
    		c[i][0]=0;
    	for(int j=0;j<length2+1;j++)
    		c[0][j]=0;
    	
    	//0 代表 ↖
            //1 代表 ↑
    	//2 代表 ←
    	for(int i=1;i<=length1;i++)
    		for(int j=1;j<=length2;j++)
    		{
    			if(str1[i-1]==str2[j-1])
    			{
    				c[i][j]=c[i-1][j-1]+1;
    				pos[i][j]=0;
    			}
    			else if(c[i-1][j]>=c[i][j-1])
    			{
    				c[i][j]=c[i-1][j];
    				pos[i][j]=1;
    			}
    			else
    			{
    				c[i][j]=c[i][j-1];
    				pos[i][j]=2;
    			}
    		}
    	cout<<"最长公共子序列长度:"<<c[length1][length2]<<endl;
    	cout<<"最长公共子序列是:";
    	ConstructLCS(pos,str1,length1,length2);
    	cout<<endl;
    }
    //构造最长子序列
    void ConstructLCS(int **pos,const char *str,int length1,int length2)
    {
    	if(length1==0||length2==0)
    		return;
    	if(pos[length1][length2]==0)
    	{
    		ConstructLCS(pos,str,length1-1,length2-1);
    		cout<<str[length1-1];
    	}
    	else if(pos[length1][length2]==1)
    		ConstructLCS(pos,str,length1-1,length2);
    	else if(pos[length1][length2]==2)
    		ConstructLCS(pos,str,length1,length2-1);
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	char *str1="abcefghkjl";
    	char *str2="bfhjkjl";
    	LCS(str1,str2,10,7);
    	system("pause");
    	return 0;
    }
    


  • 相关阅读:
    ORACLE字符串函数
    Ubuntu14.04安装wineqq国际版
    phonegap学习笔记
    Android Studio 1.5.1
    CodeBlocks+Qt(MinGW)配置
    Java多线程之synchronized(五)
    Java多线程之synchronized(四)
    Java多线程之synchronized(三)
    Java多线程之synchronized(二)
    Java多线程之synchronized(一)
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3161566.html
Copyright © 2020-2023  润新知