最長遞增子串行LIS和最長公共子串行LCS

2021-08-26 14:49:08 字數 2661 閱讀 9433

本文參考了《程式設計之美》、leetcode中文題解以及部落格

(lis)

(lcs)

特此感謝!

一、最長遞增子串行

問題描述

求乙個給定序列

比如,對於序列(1, 7, 3, 5, 9, 4, 8),有它的一些上公升子串行,如(1, 7), (3, 4, 8)等等。這些子串行中最長的長度是4,比如子串行(1, 3, 5, 8).

方法一:動態規劃

時間複雜度:o(n^2)

思路

狀態設計:f[i]代表以a[i]結尾的lis的長度

狀態轉移:f[i]=max(1<=j< i,a[j]< a[i])

邊界處理:f[i]=1(1<=i<=n)

**:

#include 

#include

#include

#include

#include

#include

using

namespace

std;

const

int maxn = 103,inf=0x7f7f7f;

int a[maxn],dp[maxn];

int n,ans = -inf;

int main()

for(int i=1;i<=n;++i)

for(int j=1;j//要求以a[x]結尾的最長遞增子串行長度,我們依次比較a[x]與之前所有的a[i](iif(a[j]1);

}for(int i=1;i<=n;++i)

ans = max(ans,dp[i]);

printf("%d\n",ans);

}}/*

61 4 3 2 6 5

*/

方法二:貪心+二分

時間複雜度:o(n^2)

思路

新建乙個low陣列,low[i]表示長度為i的lis結尾元素的最小值。對於乙個上公升子串行,顯然其結尾元素越小,越有利於在後面接其他的元素,也就越可能變得更長。

因此,我們只需要維護low陣列:

1)追加low陣列

對於每乙個a[i],如果a[i] > low[當前最長的lis長度],就把a[i]接到當前最長的lis後面,即low[++當前最長的lis長度]=a[i]。

2)更新low陣列

對於每乙個a[i],如果a[i]能接到lis後面,就接上去;否則,就用a[i]取更新low陣列。

具體方法是:

在low陣列中找到第乙個大於等於a[i]的元素low[j],用a[i]去更新low[j]。如果從頭到尾掃一遍low陣列的話,時間複雜度仍是o(n^2)。我們注意到low陣列內部一定是單調不降的,所有我們可以二分low陣列,找出第乙個大於等於a[i]的元素。二分一次low陣列的時間複雜度的o(lgn),所以總的時間複雜度是o(nlogn)。

#include 

#include

#include

#include

#include

#include

using

namespace

std;

const

int maxn =300003,inf=0x7f7f7f7f;

int low[maxn],a[maxn];

int n,ans;

int binary_search(int *a,int r,int x)

//二分查詢,返回a陣列中第乙個》=x的位置

return l;

}int main()

low[1]=a[1];

ans=1;//初始時lis長度為1

for(int i=2;i<=n;i++)

printf("%d\n",ans);//輸出答案

return

0;}

二、最長公共子串行

問題描述

求兩字串行的最長公共字元子串行

例如,字串s1=mzjawxu,s2=xmjyauz,仔細分析下,大體可以看出最長公共子串行是mjau

**

#include 

#include

#include

using

namespace

std;

//公共子串行(非連續)

int dp[1000][1000];

int lcsnotcontinus(string x,string y)

//公共子串(連續)

int lcscontinus(string x,string y)

return ans;

}int main()

公共子串要求連續,而公共子串行不要求連續,這裡參考文章:最長公共子串,使用基本方法、dp、字尾陣列等方法解決。

附:lis的問題可以通過lcs解決:

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

求最長公共子串行 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...

最長公共遞增子串行

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

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

最長公共子串行 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...