演算法 最長公共子串行 nlogn

2022-03-14 09:22:44 字數 2543 閱讀 4532

最長公共子串行(lcs)最常見的演算法是時間複雜度為o(n^2)的動態規劃(dp)演算法,但在james w. hunt和thomas g. szymansky 的**"a fast algorithm for computing longest common subsequence"中,給出了o(nlogn)下限的一種演算法。

定理:設序列a長度為n,,序列b長度為m,,考慮a中所有元素在b中的序號,即a某元素在b的序號為,將這些序號按照降序排列,然後按照a中的順序得到乙個新序列,此新序列的最長嚴格遞增子串行即對應為a、b的最長公共子串行。

舉例來說,a=,b=,則a對應在b的序號為2,b對應序號為,c對應序號為1,d對應為空集,生成的新序列為,其最長嚴格遞增子串行為,對應的公共子串行為

原**的證明過程較複雜,其實可以簡單的通過一一對應來證明。即證明a、b的乙個公共子串行和新序列的乙個嚴格遞增子串行一一對應。

(1) a、b的乙個公共子串行對應新序列的乙個嚴格遞增子串行

假設a、b的某乙個公共子串行長度為k,則其公共子串行在a和b中可以寫為

如此有ai1 = aj1,ai2 = aj2, ...., aik = ajk, 考慮元素bj1在b中的序號p(bj1),則有

p(bj1)< p(bj2) < ... < p(bjk)

注意此嚴格遞增子串行屬於新序列的乙個子串行,因此得證

(2) 新序列的乙個嚴格遞增子串行對應a、b的乙個公共子串行

設新序列的乙個嚴格遞增子串行,任意兩個相同的p不可能屬於a中同乙個元素,因為a中某元素在b中的序號按照降序排列,但此序列為嚴格遞增序列,矛盾。所以每個p均對應於a中不同位置的元素,設為。

因為p是嚴格遞增序列,則每個p也對應b中唯一的乙個元素,假設為,由p的定義可知ai1= bj1, ai2 = bj2, ...., aik = bjk,因此得證。

實現上比較複雜,有以下幾個步驟:

(1) 對序列b排序

(2) 計算a中每個元素在b中的序號,並構成新序列

(3) 使用lis的方法計算最長嚴格遞增子串行

(4) 獲取最長公共子串行

效能分析:

(1) 排序複雜度為nlogn

(2) 獲取乙個元素在b中的序號的複雜度,最小為logn,最大為n,獲取所有元素的複雜度為 nlogn === n*n

(3) lis 複雜度為nlogn

因此總體複雜度在nlogn 到 n*n logn之間,但如果(2)

步驟中a中元素在b中的序號對數很少時,效能相當優越,在實際測試時,string

中均為小寫字母,長度為10000的情況下,這種方法比普通的lcs快一倍以上;如果string

中的字元擴充套件成char,即0-255,則這種方法比普通的lcs快至少乙個數量級。

#include#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define eps 1e-9

#define all(x) x.begin(),x.end()

#define ins(x) inserter(x,x.begin())

#define for(i,j,k) for(int i=j;i<=k;i++)

#define maxn 1005

#define maxm 40005

#define inf 0x3fffffff

using

namespace

std;

typedef

long

long

ll;struct

node

u[10005

];int

i,j,k,n,m,x,y,t,ans,big,cas,num,len;

bool

flag;

bool

cmp(node a,node b)

vector

p;char a[10005],b[10005],c[10005

];int lena,lenb,dp[10005

];int

main()

sort(u,u+lenb,cmp);//

對b串排序

for (i=0;i//

排序後存入字串c中,便於使用lower_bound

c[lenb]='\0'

;

for (i=0;i//

計算a中每個元素在b中的序號

}n=p.size();

memset(dp,

0,sizeof(dp));//

計算最長上公升子串行

num=0

;

for (i=0;i)

else

}printf(

"%d\n

",num);

return0;

}

P3402 最長公共子串行(nlogn)

先看一下資料規模 n 300000,n 2的做法肯定就要掛掉了,所以用到了這個nlogn的做法。先介紹一下nlogn的做法 最長公共子串行 的 nlogn 的演算法本質是 將該問題轉化成 最長增序列 lis 因為 lis 可以用nlogn實現,所以求lcs的時間複雜度降低為 nlogn。轉化 將lc...

演算法 最長公共子串行

好久沒做演算法題了,現在發現自己的演算法能力非常薄弱,所以特意練練,順便做個筆記方便以後檢視。今天整理一下最長公共子串行,最長公共子串行的問題常用於解決字串的相似度,是乙個非常實用的演算法,作為碼農,此演算法是我們的必備基本功。最長公共子串行,是指兩個字串可具有的長度最大的公共的子串行。聽著好像有點...

演算法 最長公共子串行

題目 給定兩個字串 text1 和 text2,返回這兩個字串的最長公共子串行的長度。乙個字串的 子串行 是指這樣乙個新的字串 它是由原字串在不改變字元的相對順序的情況下刪除某些字元 也可以不刪除任何字元 後組成的新字串。例如,ace 是 abcde 的子串行,但 aec 不是 abcde 的子串行...