本文參考了《程式設計之美》、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...