1. 程式人生 > >最長遞增子序列優化演算法(時間複雜度為nlgn)C++實現

最長遞增子序列優化演算法(時間複雜度為nlgn)C++實現

最長遞增子序列優化演算法(時間複雜度為nlgn)

// 最長遞增子序列優化演算法.cpp : Defines the entry point for the console application.
//對於j位置的字元,我們需要尋找此位置之前的最大的len[i](i<j),然而len[i]是無序的
//如果len[i]有序,則可通過二分查詢快速找到
//於是我們定義一個s[]陣列,s[len[i]]儲存str[i],表示長度為len[i]的遞增子序列尾元素為str[i]。
//對於str的位置為j的元素,在s[]陣列中進行二分查詢,如果str[j]>s[mid],則查詢後半部分的s[],直到下界超過上界,
//如果str[j]<=s[mid],則查詢前半部分的s[],直到上界低於下界。
//如果下界大於當前最大長度maxLen,則更新maxLen

//時間複雜度為nlgn

#include "stdafx.h"
#include<iostream>
#define N 100
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
//儲存原字串
char str[N];
//b[j]儲存以j為長度的遞增子序列的結尾元素
char b[N];
int cases;
cout<<"請輸入案例個數:"<<endl;
cin>>cases;
while(cases--)
{
cout<<"請輸入字串:"<<endl;
cin>>str;
//初始化各變數
int i;
int length = strlen(str);
b[0] = '0'; //b[0]為最小,假設輸入的字元全部是字母
b[1] = str[0];//以1為長度的遞增子序列的結尾元素都是str[0]
int first,mid,end;//分別為二分查詢的首,中,尾位置
int maxLen = 1; //為目前遞增子序列最大長度
for(i=1;i<length;i++)
{
first = 0, end = maxLen;
while(first<=end)
{
mid = (first+end)/2;
if(b[mid]<str[i])
first = mid +1;
else
end = mid -1;
}
b[first] = str[i];
if(first>maxLen) maxLen++;
}
cout<<"最長遞增子序列的長度為:"<<maxLen<<endl;
cout<<"最長遞增子序列為:"<<endl;
for(i=1;i<=maxLen;i++)
cout<<b[i];
cout<<endl;
}
system("pause");
return 0;
}

-------------------------------------------------程式測試---------------------------------------------------------

請輸入案例個數:
2
請輸入字串:
abaceabf
最長遞增子序列的長度為:5
最長遞增子序列為:
abcef
請輸入字串:
abcabcdef
最長遞增子序列的長度為:6
最長遞增子序列為:
abcdef
請按任意鍵繼續. . .