首先,我們來介紹一下子串與子串行 的區別:子串是乙個字串中的連續字元的集合;子串行是乙個字串中任意字元的集合,不一定要連續。
然後,如何來求得最長公共子串行呢?最直接的一種方法就是暴力求解,通過比較兩個字串的所有子串行,得到公共子串行,最終得到長度最長的長度。然而這種方法的時間複雜度達到了o(2^n),可見這種方法耗時太長。
所以,我們需要一種更加高效的演算法來解決,那就是動態規劃。我們可以將求最長公共子串行分解為若干個子問題,即求str1的前i個字元
與str2的前j個字元
的最長公共子串行,我們假設用maxlen( i, j )
來表示。
那maxlen(i, j)怎麼求呢?此時,可以分為兩種情況:str1[ i - 1 ] == str2[ j - 1 ]
與str1[ i - 1 ] != str2[ j - 1 ]
(str1的第i個字元與str2的第j個字元是否相同,因為陣列從str1[0]開始,所以為i-1)。
對於第一種str1[ i - 1 ] == str2[ j - 1 ]
很好理解,因為兩個字串行的最後乙個字元相同,所以同時去掉最後乙個字元,此時長度就是maxlen(i-1, j-1)
,所以再加上最後乙個相同的字元,就得到maxlen(i, j) = maxlen(i-1, j-1) + 1
。
對於第二種情況str1[ i - 1 ] != str2[ j - 1 ]
,因為兩字串的最後乙個字元不相同,也就是說最後的字元不會同時屬於公共子串行(否則的話就成了兩子符相同的情況),因此可以分情況討論,去掉其中乙個,討論剩餘字串的最長公共子串行,選擇其中較大的乙個作為公共子串行長度,即maxlen(i, j) = max( maxlen(i-1, j), maxlen(i, j-1) )
。也就是先得出str1的左i-1個字元與str2當前子串行(前j個字元)的maxlen,再算出str1的當前子串行(前i個字元)與str2前j-1個字元的maxlen,把兩者中較大的作為maxlen(i, j)
。
乙個例題:
poj 1458 common subsequence
#include
#include
#include
using
namespace
std;
char str1[1000], str2[1000];
int maxlen[1000][1000];
int main() else }}
cout
<< maxlen[len1][len2] << endl;
}return
0;}
最長公共子串行 最長公共子串
1 最長公共子串行 採用動態規劃的思想,用乙個陣列dp i j 記錄a字串中i 1位置到b字串中j 1位置的最長公共子串行,若a i 1 b j 1 那麼dp i j dp i 1 j 1 1,若不相同,那麼dp i j 就是dp i 1 j 和dp i j 1 中的較大者。class lcs el...
最長公共子串行 最長公共子串
1.區別 找兩個字串的最長公共子串,這個子串要求在原字串中是連續的。而最長公共子串行則並不要求連續。2 最長公共子串 其實這是乙個序貫決策問題,可以用動態規劃來求解。我們採用乙個二維矩陣來記錄中間的結果。這個二維矩陣怎麼構造呢?直接舉個例子吧 bab 和 caba 當然我們現在一眼就可以看出來最長公...
最長公共子串 最長公共子串行
子串要求連續 子串行不要求連續 之前的做法是dp求子序列 include include include using namespace std const int inf 0x3f3f3f3f const int mod 1000000007 string s1,s2 int dp 1010 10...