子序列问题
最長上升子序列
n^2做法,和簡單用前一個更新,不說了;
nlogn算法:
以下轉(zhuǎn)自博客
D_Double's Journe
此外,我們用一個變量Len來記錄現(xiàn)在最長算到多少了
首先,把d[1]有序地放到B里,令B[1] = 2,就是說當只有1一個數(shù)字2的時候,長度為1的LIS的最小末尾是2。這時Len=1
然后,把d[2]有序地放到B里,令B[1] = 1,就是說長度為1的LIS的最小末尾是1,d[1]=2已經(jīng)沒用了,很容易理解吧。這時Len=1
接著,d[3] = 5,d[3]>B[1],所以令B[1+1]=B[2]=d[3]=5,就是說長度為2的LIS的最小末尾是5,很容易理解吧。這時候B[1..2] = 1, 5,Len=2
再來,d[4] = 3,它正好加在1,5之間,放在1的位置顯然不合適,因為1小于3,長度為1的LIS最小末尾應(yīng)該是1,這樣很容易推知,長度為2的LIS最小末尾是3,于是可以把5淘汰掉,這時候B[1..2] = 1, 3,Len = 2
繼續(xù),d[5] = 6,它在3后面,因為B[2] = 3, 而6在3后面,于是很容易可以推知B[3] = 6, 這時B[1..3] = 1, 3, 6,還是很容易理解吧? Len = 3 了噢。
第6個, d[6] = 4,你看它在3和6之間,于是我們就可以把6替換掉,得到B[3] = 4。B[1..3] = 1, 3, 4, Len繼續(xù)等于3
第7個, d[7] = 8,它很大,比4大,嗯。于是B[4] = 8。Len變成4了
第8個, d[8] = 9,得到B[5] = 9,嗯。Len繼續(xù)增大,到5了。
最后一個, d[9] = 7,它在B[3] = 4和B[4] = 8之間,所以我們知道,最新的B[4] =7,B[1..5] = 1, 3, 4, 7, 9,Len = 5。
于是我們知道了LIS的長度為5。
!!!!! 注意。這個1,3,4,7,9不是LIS,它只是存儲的對應(yīng)長度LIS的最小末尾。有了這個末尾,我們就可以一個一個地插入數(shù)據(jù)。雖然最后一個d[9] = 7更新進去對于這組數(shù)據(jù)沒有什么意義,但是如果后面再出現(xiàn)兩個數(shù)字 8 和 9,那么就可以把8更新到d[5], 9更新到d[6],得出LIS的長度為6。
然后應(yīng)該發(fā)現(xiàn)一件事情了:在B中插入數(shù)據(jù)是有序的,而且是進行替換而不需要挪動——也就是說,我們可以使用二分查找,將每一個數(shù)字的插入時間優(yōu)化到O(logN)~~~~~于是算法的時間復(fù)雜度就降低到了O(NlogN)~!
簡單來說就是做一個數(shù)列保存 構(gòu)成該長度子序列的所有可能中最后一個數(shù)最小的 那個序列的最后一個數(shù),可以用二分優(yōu)化,因為序列一定是上升的嘛!
#include<cstdio>
#include<iostream>
using namespace std;
int ans[100000];
int a[100000];int len=1;
inline int mid_serch(int x)
{
int l=0,r=len;
while(l<=r)
{
int mid=(l+r)>>1;
if(ans[mid]<a[x])l=mid+1;
else r=mid-1;
}
return l;
}
int main()
{
int m;
scanf("%d",&m);
for(int i=1;i<=m;++i)scanf("%d",a+i);
ans[1]=a[1];
for(int i=2;i<=m;++i)
{
if(a[i]>ans[len])
ans[++len]=a[i];
else {
int tmp=mid_serch(i);
ans[tmp]=a[i];
}
}
printf("%d",len);
}
最長公共子序列 n ^2
lcs 設(shè) A B 串
用dp[i][j]表示只考慮A串前i位,B串前j位的LCS長度。
要么A[i]和B[j]匹配不上 要么放棄A[i]要么放棄B[j]。
輕易地可以設(shè)計出狀態(tài)轉(zhuǎn)移方程。
if (a[i]==b[j]) dp[i][j]=dp[i-1][j-1]+1; else dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
復(fù)雜度O(n^2),轉(zhuǎn)移O(1);
O(“nlogn”)做法
做一個序列,保存:
串B與串A所匹配字符在串A中的位置
然后求該序列的最長上升子序列
(從前往后排)
,若果匹配項少的話復(fù)雜度 為O(nlogn)反之退化為O(n^n);
總結(jié)
- 上一篇: 你知道品牌瓷砖的价格表吗
- 下一篇: 存储引擎