• 求最长公共子序列


    最长公共子序列,英文缩写为LCS(Longest Common Subsequence)。其定义是。一个序列 S 。假设各自是两个或多个已知序列的子序列。且是全部符合此条件序列中最长的。则 S 称为已知序列的最长公共子序列。而最长公共子串(要求连续)和最长公共子序列是不同的。




    #include "stdafx.h"
    #include<deque>
    #include<iostream>
    
    using namespace std;
    
    deque<pair<char, int>>common;
    deque<pair<char, int>>max;
    deque<deque<pair<char, int>>>aa;
    int k = 0;//在str2中找到obj的位置
    int kk;
    
    
    
    deque<pair<char, int>>char2vec(char*str, int offset)
    {
    	deque<pair<char, int>>aa;
    	while (*str != '')
    	{
    		aa.push_back(pair<char, int>(*str, offset));
    		str++;
    		offset++;
    	}
    	return aa;
    }
    
    int find_char(char obj, char*str, int startpos)
    {
    	int len = strlen(str);
    	while (startpos < len)
    	{
    		if (str[startpos] == obj)
    			return startpos;
    		startpos++;
    	}
    	return -1;
    }
    
    
    void forward(char*str1, char*str2, int n)
    {
    	int len1 = strlen(str1);
    	int len2 = strlen(str2);
    	while (n < len1&&k < len2 - 1)
    	{
    		kk = find_char(str1[n], str2, k);
    		if (kk >= 0)
    		{
    			common.push_back(pair<char, int>(str1[n], kk));
    			k = kk;
    			//if (n<len1 - 1)
    			aa.push_back(char2vec(str1 + n + 1, n + 1));
    		}
    		n++;
    	}
    }
    
    
    void LMS(char*str1, char*str2)
    {
    	int len1 = strlen(str1);
    	int len2 = strlen(str2);
    	if (len1 > len2)
    	{
    		char*temp = str1;
    		str1 = str2;
    		str2 = temp;
    		int tt = len1;
    		len1 = len2;
    		len2 = tt;
    	}
    	int maxlen = 0;
    	int n = 0;//str1的索引
    
    	forward(str1, str2, n);
    	if (common.size() > maxlen)
    	{
    		maxlen = common.size();
    		max = common;
    	}
    	while (!aa.empty())
    	{
    		if (aa.back().empty())
    		{
    			aa.pop_back();
    			common.pop_back();
    			if (aa.empty())
    				return;
    		}
    		if (common.size() > 1)
    		{
    			k = common[common.size() - 2].second + 1;
    		}
    		else
    		{
    			k = 0;
    		}
    		kk = find_char(aa.back().front().first, str2, k);
    		if (kk >= 0)
    		{
    			common.pop_back();
    			common.push_back(aa.back().front());
    			common.back().second = kk;//find_char(common.back().first, str2, common[common.size() - 2].second + 1);
    			k = kk;
    			n = aa.back().front().second;
    			aa.back().pop_front();
    			forward(str1, str2, n + 1);
    			if (common.size() > maxlen)
    			{
    				maxlen = common.size();
    				max = common;
    			}
    		}
    		else
    		{
    			aa.back().pop_front();
    			if (aa.back().empty())
    			{
    				aa.pop_back();
    				common.pop_back();
    			}
    
    		}
    	}
    
    }
    
    
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	char*str1 = "adecfbaf";
    	char*str2 = "deabcabaf";
    
    	LMS(str1, str2);
    	for (int i = 0; i < max.size(); i++)
    		cout << max[i].first << endl;
    	system("pause");
    	return 0;
    }

    上述算法中common中存放当前找到的子序列。common里的pair<char,int>里的int代表这个字符在str2中的位置。

    aa中存放的是未被遍历过的字符,aa里的pair<char,int>里的int代表这个字符在str1中的位置。

    整个搜索过程是波浪式前进,common找到一个起点,走到结尾,然后替换common的结尾,再往前走。走到结尾再替换

    重复运行。过程中记录common的最大长度就可以




  • 相关阅读:
    jquery如何获取url中问号后面的数值
    CSS3 @font-face
    如何在代码中应用设计模式
    面试中可能被问到的常用排序算法
    《深入java虚拟机》读书笔记之垃圾收集器与内存分配策略
    《深入java虚拟机》读书笔记之Java内存区域
    Spring系列之手写一个SpringMVC
    Java多线程之Executor框架和手写简易的线程池
    Spring系列之手写注解与配置文件的解析
    Spring系列之AOP的原理及手动实现
  • 原文地址:https://www.cnblogs.com/cynchanpin/p/6984949.html
Copyright © 2020-2023  润新知