LICS最長公共遞增子串行

2021-09-25 22:29:47 字數 1938 閱讀 1105

最長公共上公升子串行(lcis)的o(n^2)演算法

預備知識:動態規劃的基本思想,lcs,lis。

問題:字串a,字串b,求a和b的lcis(最長公共上公升子串行)。

首先我們可以看到,這個問題具有相當多的重疊子問題。於是我們想到用dp搞。dp的首要任務是什麼?定義狀態。

1定義狀態f[i][j]表示以a串的前i個字元b串的前j個字元且以b[j]為結尾構成的lcis的長度。

為什麼是這個而不是其他的狀態定義?最重要的原因是我只會這個,還有乙個原因是我知道這個定義能搞到平方的演算法。而我這只會這個的原因是,這個狀態定義實在是太好用了。這一點我後面再說。

我們來考察一下這個這個狀態。思考這個狀態能轉移到哪些狀態似乎有些棘手,如果把思路逆轉一下,考察這個狀態的最優值依賴於哪些狀態,就容易許多了。這個狀態依賴於哪些狀態呢?

首先,在a[i]!=b[j]的時候有f[i][j]=f[i-1][j]。為什麼呢?因為f[i][j]是以b[j]為結尾的lcis,如果f[i][j]>0那麼就說明a[1]…a[i]中必然有乙個字元a[k]等於b[j](如果f[i][j]等於0呢?那賦值與否都沒有什麼影響了)。因為a[k]!=a[i],那麼a[i]對f[i][j]沒有貢獻,於是我們不考慮它照樣能得出f[i][j]的最優值。所以在a[i]!=b[j]的情況下必然有f[i][j]=f[i-1][j]。這一點參考lcs的處理方法。

那如果a[i]==b[j]呢?首先,這個等於起碼保證了長度為1的lcis。然後我們還需要去找乙個最長的且能讓b[j]接在其末尾的lcis。之前最長的lcis在哪呢?首先我們要去找的f陣列的第一維必然是i-1。因為i已經拿去和b[j]配對去了,不能用了。並且也不能是i-2,因為i-1必然比i-2更優。第二維呢?那就需要列舉b[1]…b[j-1]了,因為你不知道這裡面哪個最長且哪個小於b[j]。這裡還有乙個問題,可不可能不配對呢?也就是在a[i]==b[j]的情況下,需不需要考慮f[i][j]=f[i-1][j]的決策呢?答案是不需要。因為如果b[j]不和a[i]配對,那就是和之前的a[1]…a[j-1]配對(假設f[i-1][j]>0,等於0不考慮),這樣必然沒有和a[i]配對優越。(為什麼必然呢?因為b[j]和a[i]配對之後的轉移是max(f[i-1][k])+1,而和之前的i`配對則是max(f[i`-1][k])+1。顯然有f[i][j]>f[i`][j],i`>i)

於是我們得出了狀態轉移方程:

a[i]!=b[j]: f[i][j]=f[i-1][j]

a[i]==b[j]: f[i][j]=max(f[i-1][k])+1 1<=k<=j-1&&b[j]>b[k]

不難看到,這是乙個時間複雜度為o(n^3)的dp,離平方還有一段距離。

但是,這個演算法最關鍵的是,如果按照乙個合理的遞推順序,max(f[i-1][k])的值我們可以在之前訪問f[i][k]的時候通過維護更新乙個max變數得到。怎麼得到呢?首先遞推的順序必須是狀態的第一維在外層迴圈,第二維在內層迴圈。也就是算好了f[1][len(b)]再去算f[2][1]。

如果按照這個遞推順序我們可以在每次外層迴圈的開始加上令乙個max變數為0,然後開始內層迴圈。當a[i]>b[j]的時候令max=f[i-1][j]。如果迴圈到了a[i]==b[j]的時候,則令f[i][j]=max+1。

最後答案是f[len(a)][1]…f[len(a)][len(b)]的最大值。

#include

#include

int f[

1005][

1005

],a[

1005

],b[

1005

],i,j,t,n1,n2,max;

intmain()

} max=0;

for(i=

1;i<=n2;i++)if

(max[i]) max=f[n1]

[i];

printf

("%d\n"

,max);}

}

最長公共遞增子串行

題目描述小h最近看了諜戰電影,對裡面訊息的加密方式很感興趣,他決定和朋友試一試,小h給朋友兩個序列,兩個序列的最長公共單調遞增子串行就是要傳遞的訊息,有時候序列太長了,小h的朋友找不出來,所以他找到了你 輸入第乙個數字n表示序列長度 後面兩行每行n個數字表示小h給出的兩個序列 n 1000 輸出輸出...

最長公共子串行 最長遞增子串行 最長遞增公共子串行

求最長公共子串行 int dp maxn maxn int a maxn b maxn int main else dp i j max dp i 1 j dp i j 1 printf d n dp m n return 0 輸出最長公共子串行 int dp maxn maxn int d max...

最長公共子串行 最長遞增子串行

最長公共子串行 dp 杭電1159 include using namespace std string str1,str2 int dp 1005 1005 intlcs return dp str1.size str2.size int main 最長遞增子串行 杭電1257 include u...