公共子串行

2022-03-01 07:33:12 字數 1947 閱讀 3292

最長公共子串行問題:

給定2個字串,求其最長公共子串。如abcde和dbada的最長公共字串為bd。

動態規劃:dp[i][j]表示a串前i個和b串前j個的最長公共子串的長度。

則若a[i] == b[j] , dp[i][j] = dp[i-1][j-1] + 1;

否則 dp[i][j] = max(dp[i-1][j],dp[i][j-1]);

時間複雜度o(n*m)。

dp[i][j]僅在a[i]==b[j]處才增加,對於不相等的地方對最終值是沒有影響的。

故列舉相等點處可以對其進行優化。

則對於dp[i][j](這裡只計算a[i]==b[j]的i和j),取最大的dp[p][q],滿足(p這裡也可將其轉化為最長遞增子串行問題。

舉例說明:

a:abdba

b:dbaaba

則1:先順序掃瞄a串,取其在b串的所有位置:

2:a(2,3,5) b(1,4) d(0)。

3:用每個字母的反序列替換,則最終的最長嚴格遞增子串行的長度即為解。

替換結果:532 41 0 41 532

最大長度為3.

簡單說明:上面的序列和最長公共子串是等價的。

對於乙個滿足最長嚴格遞增子串行的序列,該序列必對應乙個匹配的子串。

反序是為了在遞增子串中,每個字母對應的序列最多只有乙個被選出。

反證法可知不存在更大的公共子串,因為如果存在,則求得的最長遞增子串行不是最長的,矛盾。

最長遞增子串行可在o(nlogn)的時間內算出。

dp[i] = max(dp[j]+1) ( 滿足 a[i] > a[j] && i > j )

顯然對於同樣的如dp[k] = 3,假定k有多個,記為看k1,k2,.....,km 設k1 < k2 < .... < km

在計算dp[i]的時候,k2,k3,....,km顯然對結果沒有幫助,取當前最小的k,

滿足ans[k] = p (最小的p使得dp[p]=k) ,每次二分,更新ans[dp[i]] = min(ans[dp[i]],i).

ps:lcs在最終的時間複雜度上不是嚴格的o(nlogn),不知均攤上是不是。

舉個退化的例子:

如a:aaa

b:aaaa

則序列321032103210

長度變成了n*m ,最終時間複雜度o(n*m*(lognm)) > o(n*m)。

這種情況不知有沒有很好的解決辦法。

附個參考**:

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

#include 

using

namespace

std;  

const

intmaxn = 1501 ;  

vector<

int> location[26] ;  

intc[maxn*maxn] , d[maxn*maxn] ;  

inline

intget_max(

inta,

intb)   

//nlogn 求lcs

intlcs(

char

a,char

b)  

d[1] = c[0] ;   d[0] = -1 ;  

for( i = ans = 1 ; i < k ; i++)  

if( r == ans ) ans++,d[r+1] = c[i] ;  

else

if( d[r+1] > c[i] ) d[r+1] = c[i] ;  

}  return

ans ;  

}  int

main()  

公共子串行

03 公共子串行 描述我們稱序列z z1,z2,zk 是序列x x1,x2,xm 的子串行,當且僅當存在嚴格上公升的序列 i1,i2,ik 使得對j 1,2,k,有xij zj。比如z a,b,f,c 是x a,b,c,f,b,c 的子串行。現在給出兩個序列x和y,你的任務是找到x和y的最大公共子串...

dp 公共子串行

描述 我們稱序列z z1,z2,zk 是序列x x1,x2,xm 的子串行當且僅當存在 嚴格上公升 的序列 i1,i2,ik 使得對j 1,2,k,有xij zj。比如z a,b,f,c 是x a,b,c,f,b,c 的子串行。現在給出兩個序列x和y,你的任務是找到x和y的最大公共子串行,也就是說要...

dp C 公共子串行

給定兩個字串 s1,s2 求它們的 lcs 滿足 s1 leq 10 6,s2 leq 10 3 考場寫了 o s1 s2 成功tle,考慮突破口為 s2 不夠大,考慮轉為判定,設 dp i j 表示原來存在最小的 k 使得 f k i geq j 不存在為 n 1 那麼 dp i j min 然後...