最長公共子序列(LCS)

        最長公共子序列,即Longest Common Subsequence,LCS。一個序列S任意刪除若干個字符獲得新序列T,則T叫作S的子序列;兩個序列X和Y的公共子序列中,長度最長的那個,定義爲X和Y的最長公共子序列。字符串13455與245576的最長公共子序列爲455。字符串acdfg與adfc的最長公共子序列爲adf。ios

         注意區別最長公共子串(Longest Common Substring),最長公共字串要求連續。 spa

// ConsoleApplication20.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <stdlib.h>

using namespace std;

const int N = 250;
int C[N][N];
int B[N][N];
enum Dir
{
	LEFT = 1,
	TOP,
	LEFTTOP
};

// 最長公共子序列
string targetStr;

void PrintDir(Dir dir)
{
	switch (dir)
	{
	case LEFT:
		cout << "-";
		break;
	case TOP:
		cout << "|";
		break;
	case LEFTTOP:
		cout << "\\";
		break;
	default:
		cout << "0";
		break;
	}
	cout << '\t';
}
// 最長公共子序列長度
int LCS_L(const char* str1, const char* str2)
{
	if (!str1 || !str2) return 0;

	const int str1Len = strlen(str1), str2Len = strlen(str2);
	const int len = max(str1Len, str2Len);

	for (int i = 0; i < len; i++)
		C[0][i] = C[i][0] = 0;

	for (int i = 1; i <= str1Len; i++)
	{
		for (int j = 1; j <= str2Len; j++)
		{
			if (str1[i-1] == str2[j-1])
			{
				C[i][j] = C[i-1][j-1] + 1;
				B[i][j] = LEFTTOP;
			}else
				if (C[i-1][j] >= C[i][j-1])
				{
					C[i][j] = C[i-1][j];
					B[i][j] = TOP;
				}
				else
				{
					C[i][j] = C[i][j-1];
					B[i][j] = LEFT;
				}
				// 當C[i-1][j] == C[i][j-1]時會出現多個最長公共子序列
		}
	}
	// Debug
	/*for (int i = 0; i <= len; i++)
	{
		if (i == 0)
		{
			cout << '0' << '\t';
			for (int k = 0; k < str2Len; k++)
				cout << str2[k] << '\t';
		}
		else
		{
			if (i <= str1Len)
				cout << str1[i-1] << '\t';
			else
				cout << '0' << '\t';

			for (int j = 1; j <= len; j++)
			{
				//PrintDir(static_cast<Dir>(B[i][j]));
				cout << C[i][j] << "\t";
			}
		}
		
		cout << endl << endl << endl << endl;
	}
	cout << "------------------------------------------------------" << endl;

	for (int i = 0; i <= len; i++)
	{
		if (i == 0)
		{
			cout << '0' << '\t';
			for (int k = 0; k < str2Len; k++)
				cout << str2[k] << '\t';
		}
		else
		{
			if (i <= str1Len)
				cout << str1[i - 1] << '\t';
			else
				cout << '0' << '\t';

			for (int j = 1; j <= len; j++)
			{
				PrintDir(static_cast<Dir>(B[i][j]));
				//cout << C[i][j] << "\t";
			}
		}

		cout << endl << endl << endl << endl;
	}
	cout << "------------------------------------------------------" << endl;*/
	return C[str1Len][str2Len];
}

// 獲取最長公共子序列
void LCS(const char* str, int i, int j)
{
	if (!str || i == 0 || j == 0) return;
	
	switch (B[i][j])
	{
	case LEFT:
		LCS(str, i, j - 1);
		break;
	case LEFTTOP:
		cout << str[i - 1];
		targetStr.insert(targetStr.begin(), str[i - 1]);
		LCS(str, i - 1, j - 1);
		break;
	case TOP:
		LCS(str, i - 1, j);
		break;
	default:
		break;
	}
}


int _tmain(int argc, _TCHAR* argv[])
{

	char str1[100], str2[100];
	cin >> str1 >> str2;
	
	cout << LCS_L(str1, str2) << endl;

	LCS(str1, strlen(str1), strlen(str2));
	cout << endl;
	cout << targetStr.c_str() << endl;
	return 0;
}
相關文章
相關標籤/搜索