摘要:題目給定兩個(gè)字符串求出它們的最長公共字串說明比如在單詞和它們的最長公共子序列是。最長公共子串和最長公共子序列的區(qū)別。
題目
給定兩個(gè)字符串,求出它們的最長公共字串
var str1="abcdefg"; var str2="xyzabcd";
說明:比如在單詞"abcdefg"和"abcdefg"它們的最長公共子序列是"abcd"。尋找最長子序列常用于遺傳學(xué)中,用于使用核苷酸堿基的首字母對DNA的描述(這段話從網(wǎng)上抄的)。
最長公共子串和最長公共子序列的區(qū)別。
最長公共子串和最長公共子序列的區(qū)別為:子串是串的一個(gè)連續(xù)的部分,子序列則是從不改變序列的順序,而從序列中去掉任意的元素而獲得新的序列;也就是說,子串中字符的位置必須是連續(xù)的,子序列則可以不必連續(xù)。
這道題,想了很長時(shí)間,終于慢慢的把題目做出來了,接下來的內(nèi)容可能會很難理解,也許我比較笨吧至少對我來說想了好久。我會盡量結(jié)合圖文去展示解題的思路,也可以自己想想,然后在看接下來的內(nèi)容。
暴力破解其實(shí)看到這個(gè)問題我們直接可以用暴力的方式解決這個(gè)問題。給定兩個(gè)字符串A和B,我們可以通過從A的第一個(gè)字符開始與B對應(yīng)的每一個(gè)字符進(jìn)行對比的方式找到最長的公共字串。如果此時(shí)沒有找到匹的字母,則移動到A的第二個(gè)字符處,然后從B的第一個(gè)字符處進(jìn)行對比,以此類推。由于下面的內(nèi)容較多,爆力方法我這里就不寫了。
動態(tài)規(guī)劃我們回顧一下動態(tài)規(guī)劃的解題思路:
從底部開始解決問題,將所有小問題解決掉,然后合并成一個(gè)整體的解決方案。
使用一個(gè)數(shù)組建立一張表,用于存放被分解成眾多子問題的解。
那基于這兩點(diǎn)我們首先要分解這個(gè)問題,怎么分解呢?
第一步: 最小的是每個(gè)字符,所以要把分解成單個(gè)的字符去匹配每個(gè)單個(gè)的字符。因此這里我們可以得到下面這一張表:
匹配為1,不匹配為0,這個(gè)時(shí)候我們就分解成為每個(gè)字符的匹配情況,由此得到。
第二步: 每個(gè)子問題有了,這個(gè)時(shí)候我們要建立一個(gè)數(shù)組去存放每個(gè)子問題的解。關(guān)鍵問題在于,我們怎么樣把每個(gè)子問題的解存起來,并且可以得到我們想要的結(jié)果。對表做一些處理,初始化一個(gè)二維數(shù)組:
var arr = new Array(str1.length + 1); for (var i = 0; i <= str1.length + 1; i++) { arr[i] = new Array(str2.length + 1); for (var j = 0; j <= str2.length + 1; j++) { arr[i][j] = 0; } }
得到如下的表:
圖中我們可以看到行和列都多加了一個(gè)并且都是0,這是為了判斷上一個(gè)是否相等的操作,后面你就會明白它的意思了。
對初始化的二維數(shù)組坐些處理,得到如下圖:
一開始看到這個(gè)圖的時(shí)候你可能會很懵逼,如果你已經(jīng)看明白了,那你就跳過我這段廢話吧。我們應(yīng)該一直的告訴自己,新建的這個(gè)數(shù)組是存放每個(gè)子問題的解,首先要明確的是找出最長字串,有哪些方式可以做到把字串從原來的字符串中截取,所以要知道起始位置和字串的長度。從圖中可以看到的紅字就是存放這個(gè)位置的最優(yōu)解字串的長度,所以應(yīng)該建立兩個(gè)變量去存儲其實(shí)位置的index 和最大長度 maxLen 。得到一下代碼:
var maxLen = 0; var index = 0; for(var i = 0; i <= str1.length; i++){ for(var j = 0; j <= str2.length; j++){ if(i == 0 || j == 0){ arr[i][j] = 0 }else{ if (str1[i] == str2[j] && str1[i - 1] == str2[j - 1]) { arr[i][j] = arr[i - 1][j - 1] + 1; }else{ arr[i][j] = 0; } } if(arr[i][j] > maxLen){ maxLen = arr[i][j]; index = i; } } }
簡單的解釋一下,這里要明確連續(xù)的字串的位置,是二維數(shù)組對角線上的值,這點(diǎn)明確了很多問題就好理解了。
上面的代碼把最主要的兩個(gè)參數(shù)找到了,那接下來就是選擇其中的一個(gè)字符串去截取字串:
var str = ""; if(maxLen == 0){ return ""; }else{ for(var k = index - maxLen; k < maxLen; k++){ str += str1[k]; } return str; }
下面貼上完整的代碼,你也可以去我的github上查看源碼;
function LCS(str1, str2){ var maxLen = 0; var index = 0; var arr = new Array(); for (var i = 0; i <= str1.length + 1; i++) { arr[i] = new Array(); for (var j = 0; j <= str2.length + 1; j++) { arr[i][j] = 0; } } for(var i = 0; i <= str1.length; i++){ for(var j = 0; j <= str2.length; j++){ if(i == 0 || j == 0){ arr[i][j] = 0 }else{ if (str1[i] == str2[j] && str1[i - 1] == str2[j - 1]) { arr[i][j] = arr[i - 1][j - 1] + 1; }else{ arr[i][j] = 0; } } if(arr[i][j] > maxLen){ maxLen = arr[i][j]; index = i; } } } var str = ""; if(maxLen == 0){ return ""; }else{ for(var k = index - maxLen; k < maxLen; k++){ str += str1[k]; } return str; } } var str1="abcdefg"; var str2="xyzabcd"; LCS(str1, str2) // abcd
到此為止我們終于找到了最長公共字串。到這里我們需要想想能不能在優(yōu)化了,雖然這樣解決問題,但是引入了一個(gè)二維數(shù)組,在兩個(gè)字符串都較大的情況下不是很劃算,是否可以進(jìn)一步優(yōu)化?答案是可以的,需要改變一下策略,是否可以建立一個(gè)一維數(shù)組就可以解決問題了呢,這里晚了先寫這么多把,之后我會在公眾號中貼出暴力解法和動態(tài)規(guī)劃的優(yōu)化解法,歡迎持續(xù)關(guān)注我的公眾號獲得一手的信息。
歡迎關(guān)注微信公眾賬號查看最新文章
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/86727.html
摘要:源代碼管理中,指令,可以查找出編輯前后文件的差異,這是基于動態(tài)規(guī)劃實(shí)現(xiàn)的。編輯距離,判斷字符串的相似程度,也是基于動態(tài)規(guī)劃計(jì)算。 本文是《算法圖解》筆記 應(yīng)用場景 一切脫離實(shí)際應(yīng)用場景的算法都是耍流氓! 生物學(xué)家根據(jù)最長公共序列來確定 DNA 鏈的相似性,進(jìn)而判斷兩種動物或疾病有多相似。最長公共序列還被用來尋找多發(fā)性硬化癥治療方案。 源代碼管理中,git diff指令,可以查找出編輯...
摘要:若且,則是和的最長公共子序列若且,則是和的最長公共子序列。遞歸結(jié)構(gòu)容易看到最長公共子序列問題具有子問題重疊性質(zhì)。例如,在計(jì)算和的最長公共子序列時(shí),可能要計(jì)算出和及和的最長公共子序列。 雖是讀書筆記,但是如轉(zhuǎn)載請注明出處 http://segmentfault.com/blog/exploring/ .. 拒絕伸手復(fù)制黨 本章講解: 1. LCS(最長公共子序列)O(n^2)的時(shí)間復(fù)雜...
摘要:遇到問題查查,看看,大神的講解問問島胖君下面是我最近整理出來的關(guān)于字符串的文章的怎么翻譯匯集目錄非常希望強(qiáng)化博客的功能,比如分類,置頂。 雖是讀書筆記,但是如轉(zhuǎn)載請注明出處 http://segmentfault.com/blog/exploring/ .. 拒絕伸手復(fù)制黨 最近在看算法和語言,基本屬于看知識 --> java實(shí)現(xiàn) --> 整理blog 這個(gè)路線。 遇到問題查查st...
摘要:最長公共子序列問題指的是求解兩個(gè)序列和的長度最長的公共子序列。當(dāng)然,可以看出,問題容易出現(xiàn)重疊子問題,這時(shí)候,就需要用動態(tài)規(guī)劃法來解決。 問題介紹 ??給定一個(gè)序列$X=$,另一個(gè)序列$Z=$滿足如下條件時(shí)稱為X的子序列:存在一個(gè)嚴(yán)格遞增的X的下標(biāo)序列${i_1,i_2,...,i_k}$,對所有的$j=1,2,...,k$滿足$x_{i_j}=z_j.$??給定兩個(gè)序列$X$和$Y$...
摘要:最長公共子序列問題指的是求解兩個(gè)序列和的長度最長的公共子序列。當(dāng)然,可以看出,問題容易出現(xiàn)重疊子問題,這時(shí)候,就需要用動態(tài)規(guī)劃法來解決。 問題介紹 ??給定一個(gè)序列$X=$,另一個(gè)序列$Z=$滿足如下條件時(shí)稱為X的子序列:存在一個(gè)嚴(yán)格遞增的X的下標(biāo)序列${i_1,i_2,...,i_k}$,對所有的$j=1,2,...,k$滿足$x_{i_j}=z_j.$??給定兩個(gè)序列$X$和$Y$...
閱讀 1166·2021-11-11 16:55
閱讀 3052·2021-08-16 11:00
閱讀 2895·2019-08-30 15:56
閱讀 3435·2019-08-30 11:24
閱讀 3416·2019-08-30 11:05
閱讀 3531·2019-08-29 15:15
閱讀 2615·2019-08-26 13:57
閱讀 2554·2019-08-23 18:17