此前在動態規劃一講:動態規劃(3)-最長遞增子串行 曾說過此問題,當前是的雙重迴圈是o(n^2)的複雜度。
後來在網上看到說lis問題有o(nlogn)的演算法,於是拿來小研究了一下。
這個演算法其實已經不是dp了,有點像貪心。至於複雜度降低其實是因為這個演算法裡面用到了二分搜尋。本來有n個數要處理是o(n),每次計算要查詢n次還是o(n),一共就是o(n^2);現在搜尋換成了o(logn)的二分搜尋,總的複雜度就變為o(nlogn)了。
這個演算法的具體操作如下(by ryanwang):
開乙個棧,每次取棧頂元素top和讀到的元素temp做比較,如果temp > top 則將temp入棧;如果temp < top則二分查詢棧中的比temp大的第1個數,並用temp替換它。 最長序列長度即為棧的大小top。
這也是很好理解的,對於x和y,如果x < y且stack[y] < stack[x],用stack[x]替換stack[y],此時的最長序列長度沒有改變但序列q的」潛力」增大了。
舉例:原序列為1,5,8,3,6,7
棧為1,5,8,此時讀到3,用3替換5,得到1,3,8; 再讀6,用6替換8,得到1,3,6;再讀7,得到最終棧為1,3,6,7。最長遞增子串行為長度4。
用該演算法完成poj2533的具體**如下:
#include #define size 1001
using namespace std;
int main()
else
else
}/* 用temp替換 */
stack[low] = temp;}}
/* 最長序列數就是棧的大小 */
cout << top << endl;
//system("pause");
return 0;
}
這其中用到了二分查詢第乙個大於等於的,其實c++裡面的有乙個函式可用代替二分。
lower_bound 函式
下面是使用lower_bound優化最長上公升子串行。由於長度相同的上公升子串行只需要儲存結尾最小的那個,而長度遞增時,結尾數字的大小也是遞增的。最長上公升子串行就是找出比他大的第乙個數。前面的數都比他小,所以他和這個數的長度相同。然後由於他比較然後小,更新找到的那個值。
#include#include#includeusing namespace std;
int num[10]=;
const int inf=0x3f3f3f3f;
int l=10;
int g[100];
int d[100];
int main()
else
else
}/* 用temp替換 */
stack[low] = temp;}}
/* 最長序列數就是棧的大小 */
cout << top << endl;
//system("pause");
return 0;
}
HAOI2010 最長上公升子串行長度
題目描述 字串行的子串行是指從給定字串行中隨意地 不一定連續 去掉若干個字元 可能乙個也不去掉 後所形成的字串行。令給定的字串行x x0,x1,xn 1 序列y y0,y1,yk 1是x的子串行,存在x的乙個嚴格遞增下標序列 使得對所有的j 0,1,k 1,有xij yj。例如,x abcbdab ...
動態規劃 求最長上公升子串行長度
問題描述 求最長上公升子串行長度 include include include using namespace std const int maxn 1010 int a maxn 儲存輸入的資料 int maxlen maxn 儲存從開始到每乙個資料中最長上公升子串行長度 int main fo...
尋找最長上公升子串行(長度及輸出)
include include int max int a,int b void display int tempmaxs,int index,int data,int maxlength printf 最長上公升子串行為 n for i count i 0 i printf d path i pr...