(一)最長公共子串行(lcs):
我們用xi代表, 用yj代表。那麼,求長度分別為n,m的兩個序列x, y的lcs,就相當於求xm與yn的lcs。
我們可以將其分割為區域性問題進行分析,要考慮如下兩種情況:
xm = yn時, 在xm-1與yn-1的lcs後面加上xm( = yn)就是xm與yn的lcs
xm ≠yn時,xm-1與yn的lcs和xm與yn-1的lcs中更長的一方就是xm與yn的lcs
設有c[m+1][n+1],該二維陣列中c[i][j]表示xi與yj的lcs長度,由遞推公式可得:
if i = 0 or j = 0 : c[i][j] = 0;
if i, j > 0 and xi = yj : c[i][j] = c[i-1][j-1]+1;
if i, j > 0 and xi ≠ yj: c[i][j] = max(c[i][j-1], c[i-1][j]);
具體**如下:
int lcs(string x, string y)
} return maxl;
}
(二)最長上公升子串行(lis):
(1)o(n²)解法:
定義dp[i]表示以第i個位置的數作為子串行中最後乙個元素時,能構成的子串行的最大長度,轉移方程如下:
dp[i] = max(dp[i], dp[j]+1) j < i && a[j] < a[i];
int maxl = 0;
for(int i = 0; i < a.size(); i++)
maxl = max(maxl, dp[i]);
}
(2) o(nlogn)解法:
定義min[i],表示在處理當前位置時,由之前元素構成的所有長度為i的子串行中,最後乙個元素的最小值。可知min陣列是乙個遞增陣列,
對於當前整數a[x],只需在min中找到最大的乙個比a[x]小的數所在位置j即可, j+1便是a[x]能夠出現在所有子串行中最大的位置,該過程
可用二分查詢的方式來進行。
例題 toj -- 1765 :
#include#includeusing namespace std;
int dp[10005];
int main()
//新加入的數能夠使得可得到的最長子序列長度增加
if(low >= tail)
tail++;
dp[low] = a;
} cout << tail << endl;
} return 0;
}
(三)最長公共上公升子串行(lcis):
例題 hdu--1423: 採用了乙個一維演算法
#include#include#include#includeusing namespace std;
long long int a[505], b[505], f[505];
int main()
scanf("%d", &n2);
for(int i = 1; i <= n2; i++)
memset(f, 0, sizeof(f));
for(int i = 1; i <= n1; i++)
} max = 0;
for(int i = 1; i <= n2; i++)
cout << max << endl;
} }return 0;
}
最長子序列
最長子序列可以說是剛接觸動態規劃的人經常遇見也不得不解決的問題,最常見的有兩種,一種是最長公共子串行 lcs 還有乙個是最長上公升子串行 lis 今天我就總結下這兩個的做法。一 最長公共子串行 lcs 題目描述 給你兩個陣列,可以是數字的,也可以是字串,我們假設是數字的!舉個例子 x 1,5,6,4...
最長子序列
在做oj題目的時候,經常會用到字串的處理。例如,比較二個字串相似度。這篇文章介紹一下求兩個字串的最長公共子串行。乙個字串的子串行,是指從該字串中去掉任意多個字元後剩下的字元在不改變順序的情況下組成的新字串。最長公共子串行,是指多個字串可具有的長度最大的公共的子串行。include includech...
最長子序列
題 給定乙個長度為n的陣列,找出乙個最長的單調自增子序列 不一定連續,但是順序不能亂 例如 給定乙個長度為8的陣列a,則其最長的單調遞增子串行為,長度為6。思路1 第一眼看到題目,很多人肯定第一時間想到的是lcs。先給陣列排個序形成新陣列,然後再把新陣列和原陣列拿來求lcs,即可得到答案。這種解法很...