這是三道典型的dp問題。
最長上公升子串行:
在一列數中尋找一些數,這些數滿足:任意兩個數a[i]和a[j],若i設dp[i]表示以i為結尾的最長遞增子串行的長度,則狀態轉移方程為:dp[i] = max, 1<=j考慮兩個數a[x]和a[y],x
最大連續子串行和:在一列數中尋找一些數,這些數滿足:任意兩個數a[i]和a[j],若i+1=j,必有a[i]
最長公共子串:兩個字串中的最常公共連續子串。
找 兩個字串的最長公共子串,這個子串要求在原字串中是連續的。其實這又是乙個序貫決策問題,可以用動態規劃來求解。我們採用乙個二維矩陣來記錄中間的結 果。這個二維矩陣怎麼構造呢?直接舉個例子吧:"bab"和"caba"(當然我們現在一眼就可以看出來最長公共子串是"ba"或"ab")
b a b
c 0 0 0
a 0 1 0
b 1 0 1
a 0 1 0
我們看矩陣的斜對角線最長的那個就能找出最長公共子串。
不過在二維矩陣上找最長的由1組成的斜對角線也是件麻煩費時的事,下面改進:當要在矩陣是填1時讓它等於其左上角元素加1。
b a b
c 0 0 0
a 0 1 0
b 1 0 2
a 0 2 0
這樣矩陣中的最大元素就是 最長公共子串的長度。
因此我們需要維護乙個二維陣列,行數為第乙個字串的長度,列數為第二個字串的長度。為了擷取子串,那麼我們需要子串的起始和結束索引。借助之前的分析,因為dp裡記錄的是到某個節點的長度,因此我們可以通過維護乙個長度和結束索引來變相的記錄子串的起始和結束索引。
/*** 最長遞增子串行
* * @param nums
* @return
*/public
intgetlis
(int nums)
int max =
1;int dp =
newint[nums.length];
for (
int i =
0; i < nums.length; i++) }}
return max;
}/**
* 最長遞增子串行
* * @param nums
* @return
*/public
intgetlis
(int nums)
arraylistdp =
new arraylist<>();
for (
int item : nums)
else
}return dp.size();
}/**
* 最大連續子串行和
* * @param nums
* @return
*/public
intgetmaxsubarray
(int nums)
int maxendinghere =
0;int maxsofar = integer.min_value;
for (
int i =
0; i < nums.length; i++)
maxendinghere += nums[i];
maxsofar = math.max(maxsofar, maxendinghere);
}return maxsofar;
}/**
* 最長公共子串
* * @param a
* @param b
* @return
*/public string getlcs
(string a, string b)
int dp =
newint[a.length()][b.length()];
int endhere =
0;int maxlen =
0;for (
int i =
0; i < a.length(); i++)
else
if (dp[i][j] > maxlen) }}
return a.substring(endhere - maxlen +
1, endhere +
1);}
動態規劃典型題 最長公共子串行
問題描述 我們稱序列 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的最大公共...
31 最大連續子串行和(三)
一.最大子串行和 聯機演算法 在前兩篇博文中,我們了解了兩種較差演算法,和一種分治演算法。下面我們講解乙個更好的方法 聯機演算法。這種演算法的時間複雜度是 o n 這個方法也是解決這個問題的最好演算法,因為無論如何,讀取資料也要 n 次。1.例項分析 給定一組資料,data 1,4,3,7,6,10...
LintCode刷題 最長上公升連續子串行
問題描述 給定乙個整數陣列 下標從 0 到 n 1,n 表示整個陣列的規模 請找出該陣列中的最長上公升連續子串行。最長上公升連續子串行可以定義為從右到左或從左到右的序列。樣例 給定 5,4,2,1,3 其最長上公升連續子串行 lics 為 5,4,2,1 返回4.給定 5,1,2,3,4 其最長上公...