最長公共子串行 的 nlogn 的演算法本質是 將該問題轉化成 最長增序列(lis),因為 lis 可以用nlogn實現,所以求lcs的時間複雜度降低為 nlogn。
1. 轉化:將lcs問題轉化成lis問題。
假設有兩個序列 s1[ 1~6 ] = , s2[ 1~7 ] = 。
記錄s1中每個元素在s2中出現的位置, 再將位置按降序排列, 則上面的例子可表示為:
loc( a)= , loc( b ) = , loc( c ) = , loc( d ) = 。
將s1中每個元素的位置按s1中元素的順序排列成乙個序列s3 = 。
在對s3求lis得到的值即為求lcs的答案。(這點我也只是大致理解,讀者可以自己理解甚至證明。)
2.求lis的 nlogn 的演算法:
覆蓋:是序列s的幾個不相交的降序列,它們包含了s中的所有元素,降序列的個數為c。
最小覆蓋:c值最小的覆蓋。
定理:序列s的最長增序列等於最小覆蓋。
於是:求s的最長增序列轉化成求s的最小覆蓋。
3.求最小覆蓋的 nlogn 的演算法。
上圖來自鏈結中的pdf,其中 (i, j)表示序列中第 j 個降序列的最後乙個元素是 i 。可用以為陣列a實現這個記錄。
初始化,a[ 1 ] = s[ 1 ]。
對序列s中第i個元素進行處理時,都盡量將這個元素加到之前的降序列中最後乙個元素最小的那個降序列的後面(類似貪心的思想),可保證求得的是最小覆蓋,由圖可知之前的降序列的最後乙個元素是公升序排列的,此時可以用二分搜尋最後乙個元素最小的且大於等於元素i的降序列,將元素i加到這個序列後面。
當然,若沒有這樣的序列,就再建乙個降序列,目前的最後乙個元素為元素i。
下面是一道題
**附上:
#include #include #include using namespace std;
#define len 100005
int a[len], b[len];
int loc[len], n;
void calloc()
int lis()
a[l] = b[i];
} }return k;
}int main()
return 0;
}
A 演算法總結
1 把起點加入 open list 2 重複如下過程 a 遍歷 open list 查詢 f 值最小的節點,把它作為當前要處理的節點。b 把這個節點移到 close list c 對當前方格的 8 個相鄰方格的每乙個方格?如果它是不可抵達的或者它在 close list 中,忽略它。否則,做如下操作...
演算法導論 排序演算法總結
從六月初開始看演算法導論,陸陸續續看了有2個月了,但實際看的時間只有半個月左右。這期間都忙著找導師 期末考試,同時還回家修養了十來天。真正專心的看演算法是在離家返校後,由於沒有考試和作業的煩惱,天天都沉浸在演算法中,感覺效率較高。這段時間學到的東西較多,下面來總結一下 比較排序有 插入排序法 合併排...
回溯演算法 演算法總結(四)
回溯算法也叫試探法,它是一種系統地搜尋問題的解的方法。回溯演算法的基本思想是 從一條路往前走,能進則進,不能進則退回來,換一條路再試。用回溯演算法解決問題的一般步驟為 1 定義乙個解空間,它包含問題的解。2 利用適於搜尋的方法組織解空間。3 利用深度優先法搜尋解空間。4 利用限界函式避免移動到不可能...