1. 程式人生 > >Nakatsu演算法--C++實現

Nakatsu演算法--C++實現

    期末論文選的是最長公共子序列的其他解法,偶然發現Nakatsu演算法對於最長公共子序列求解速度很快。嘔心瀝血寫的程式碼=。=| 希望可以給以後想學習用Nakatsu演算法的朋友們一個參考。 注:Nakatsu求的是最佳匹配度,子序列可能所含字元不正確,但卻是基於Nakatsu演算法的最佳匹配,求得的最長公共子序列的長度是一定對的。(沒用使用STL容器,不是很熟練)

/******************************************
程式碼說明:
本程式定義了二維動態陣列L[][]用來儲存Nakatsu演算法中計算相同字元對應位置的矩陣
最大值即不存在相等的字元
若L[][]對角線上任意一個位置為最大值,對角線上其餘位置也是最大值,即本條對角線上不存在最大公共子序列
*******************************************/

//Nakatsu求解的是基於自身演算法的最長公共子序列的最佳匹配度,在某些情況可能與最長公共子序列有所偏差,即長度一致,字元可能會偏差少許
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;
void LCS_N(const string& a, const string& b)
{

	unsigned int i = 0;//迴圈控制變數也當做L[][i]陣列列下標
	unsigned int j = 0;//迴圈控制變數
	unsigned int m = a.length();//短字串長度
	unsigned int n = b.length();//長字串長度
	unsigned p = m-1;//記錄最長子序列長度
	unsigned int k=1;//L[k][]陣列行下標

	unsigned int **L = new unsigned int *[m];//字元位置矩陣
	for (i = 0; i < m; i++)
		L[i] = new unsigned int[m];

	for (i = 0; i < m; i++)//將 下面的一條次對角線 初始化為最大值,對於unsigned int來說,-1,就是最大值
	{
		j = i + 1;
		if (j < m)
			L[j][i] = -1;
	}//for
	for (j = 0; j < m; j++)
		L[0][j] = 0;//第0行初始化為0


	for (unsigned int x=1;x<m;x++)
	{
		k=1;
		i=x;
		for(j=1;j<n&&i<m;j++)//匹配a[i]與b[j]
		{
			if(a[i]==b[j]||j>=L[k][i-1])
			{
				L[k][i]=j;
				k++;
				i++;
			}

		}
		//結束迴圈時,L[k][i]可能未賦值,L[k][i-1]可能為正常的值
		while(i<m)//如果未跳出迴圈,對這條對角線的剩餘元素賦值,由於L[k][i-1]或為最大值,或為正常值,因此可以直接將L[k][i-1]賦值給L[k][i]
		{
			L[k][i]=L[k][i-1];
			i++;
			k++;
		}
		if(L[k-1][i-1]!=-1)//如果這條對角線最後一個元素不為最大值(即-1),說明找到完整對角線,跳出迴圈
			break;
		p--;

	}

	for(i=0;i<m;i++)//輸出最長子序列位置(位置對應著長字串中的字元),即完整的對角線上的數列,
	{
		for(j=0;j<m;j++)
			cout<<setw(11)<<L[i][j]<< "  ";
		cout<<endl;
	}//for
	
	cout<<"最長公共子序列長度為:"<<p<<endl;//輸出最長公共子序列長度
	
	if(m-x!=0)
	{
		cout<<"最長公共子序列為:";
		for(i=1,j=x;i<=p;i++,j++)//輸出最長公共子序列(最佳匹配)
			cout<<b[L[i][j]];
		cout<<endl;
	}
	
	for (i = 0; i < k; i++)//釋放動態陣列空間
		delete[] L[i];
	delete[] L;
}
int main()
{
	string a;
	string b;
	cout << "Please enter the first string:" << endl;
	cin >> a;
	cout << "Please enter the second string:" << endl;
	cin >> b;
	a = " " + a;
	b = " " + b;
	swap(a, b);
	LCS_N(a, b);
	return 0;
}