JavaScript實(shí)現(xiàn)求最大公共子串的方法
本文實(shí)例講述了JavaScript實(shí)現(xiàn)求最大公共子串的方法。分享給大家供大家參考,具體如下:
求最大公共子串,常見的做法是使用矩陣。假設(shè)有字符串:abcdefg和字符串a(chǎn)bcd,則可構(gòu)成如下表所示矩陣。
| a | b | c | d | e | f | g | |
| a | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
| b | 0 | 1 | 0 | 0 | 0 | 0 | 0 |
| c | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
| d | 0 | 0 | 0 | 1 | 0 | 0 | 0 |
對(duì)兩個(gè)字符串的每一項(xiàng)都進(jìn)行比較,若匹配則該項(xiàng)為1,不匹配則為0。然后求出對(duì)角線最長(zhǎng)為1的那一段序列,即為最大公共子串??瓷厦娴姆珠_,似乎得使用二維數(shù)組了,在兩個(gè)字符串都較大的情況下不是很劃算,是否可以進(jìn)一步優(yōu)化?
可以,需要改變一下策略,如果該項(xiàng)匹配,則該項(xiàng)的值為再設(shè)為1,而是其對(duì)角線a[i-1, j-1](i > 1 && j > 1)的值+1,這樣便可以只使用一個(gè)一維數(shù)組。
以一個(gè)字符串作為“行”,另一個(gè)作為“列”,比較兩個(gè)字符串各項(xiàng)的值,用另外一個(gè)變量記錄數(shù)組的最大值和字符串的起始位置。代碼如下:
function LCS(str1, str2) {
if (str1 === "" || str2 === "") {
return "";
}
var len1 = str1.length;
var len2 = str2.length;
var a = new Array(len1);
var maxLen = 0;
var maxPos = 0;
for (var i = 0; i < len1; i++) { //行
for (var j = len2 - 1; j >= 0; j--) {//列
if (str1.charAt(j) == str2.charAt(i)) {
if (i === 0 || j === 0) {
a[j] = 1;
} else {
a[j] = a[j - 1] + 1;
}
} else {
a[j] = 0;
}
if (a[j] > maxLen) {
maxLen = a[j];
maxPos = j;
}
}
}
return str1.substr(maxPos - maxLen + 1, maxLen);
}
但代碼其實(shí)并不是最優(yōu)的,為什么?因?yàn)樯厦娴膶懛ū仨毜却齼蓪友h(huán)都完成。有沒有相對(duì)更快一些的方法呢?
設(shè)有字符串a(chǎn)、b,其長(zhǎng)度分別為len1、len2,其公共字子串一定是 <= Math.min(len1, len2),而且子串必定連續(xù),且一定是a、b的子串。
function findMaxSubStr(s1,s2){
var str= "",
L1=s1.length,
L2=s2.length;
if (L1>L2){
var s3=s1;
s1=s2;
s2=s3;
s3 = null;
L1=s2.length;
L2 = s1.length;
}
for (var i=L1; i > 0; i--) {
for (var j= 0; j <= L2 - i && j < L1; j++){
str = s1.substr(j, i);
if (s2.indexOf(str) >= 0) {
return str;
}
}
}
return "";
}
先比較s1、s2的長(zhǎng)度,然后取較短的字符串作為。substr(idex, len),所以拿較短的串取其子串,然后判斷它是否在較長(zhǎng)的字符串中存在,如果存中則直接返回,否則再取下一位。
完整示例:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>www.dbjr.com.cn</title>
<style type='text/css'>
body {background-color:#fff;}
</style>
</head>
<body>
<script type='text/javascript'>
function LCS(str1, str2) {
if (str1 === "" || str2 === "") {
return "";
}
var len1 = str1.length;
var len2 = str2.length;
var a = new Array(len1);
var maxLen = 0;
var maxPos = 0;
for (var i = 0; i < len1; i++) { //行
for (var j = len2 - 1; j >= 0; j--) {//列
if (str1.charAt(j) == str2.charAt(i)) {
if (i === 0 || j === 0) {
a[j] = 1;
} else {
a[j] = a[j - 1] + 1;
}
} else {
a[j] = 0;
}
if (a[j] > maxLen) {
maxLen = a[j];
maxPos = j;
}
}
}
return str1.substr(maxPos - maxLen + 1, maxLen);
}
function findMaxSubStr(s1,s2){
var str= "",
L1=s1.length,
L2=s2.length;
if (L1>L2) {
var s3=s1;
s1=s2;
s2=s3;
s3 = null;
L1=s2.length;
L2 = s1.length;
}
for (var i=L1; i > 0; i--) {
for (var j= 0; j <= L2 - i && j < L1; j++){
str = s1.substr(j, i);
if (s2.indexOf(str) >= 0) {
return str;
}
}
}
return "";
}
!(function() {
var tmpArr = [];
for (var i = 97; i < 97 + 26; i++) {
tmpArr.push(String.fromCharCode(i));
}
var s2 = tmpArr.join("");
tmpArr.sort(function() {return Math.random() > 0.7;});
var s1 = new Array(600).join(tmpArr.join(""));
var date = getNow();
alert( "消耗時(shí)間:" + (getNow() - date) + "秒 " + LCS(s1, s2));
date = getNow();
alert( "消耗時(shí)間:" + (getNow() - date) + "秒 " + findMaxSubStr(s1, s2) );
})();
function getNow() {
return new Date().getTime();
}
</script>
</body>
</html>
更多關(guān)于JavaScript相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》、《JavaScript數(shù)組操作技巧總結(jié)》、《JavaScript排序算法總結(jié)》、《JavaScript遍歷算法與技巧總結(jié)》、《JavaScript查找算法技巧總結(jié)》及《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》
希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。
- JavaScript自定義函數(shù)實(shí)現(xiàn)查找兩個(gè)字符串最長(zhǎng)公共子串的方法
- js判斷一個(gè)字符串是否包含一個(gè)子串的方法
- js判斷出兩個(gè)字符串最大子串的函數(shù)實(shí)現(xiàn)方法
- JS使用正則表達(dá)式找出最長(zhǎng)連續(xù)子串長(zhǎng)度
- 在JavaScript中訪問字符串的子串
- JavaScript檢查子字符串是否在字符串中的方法
- JavaScript判斷一個(gè)字符串是否包含指定子字符串的方法
- javascript查找字符串中出現(xiàn)最多的字符和次數(shù)的小例子
- js中通過split函數(shù)分割字符串成數(shù)組小例子
- JavaScript計(jì)算字符串中每個(gè)字符出現(xiàn)次數(shù)的小例子
- javascript下搜索子字符串的的實(shí)現(xiàn)代碼(腳本之家修正版)
相關(guān)文章
用云開發(fā)Cloudbase實(shí)現(xiàn)小程序多圖片內(nèi)容安全監(jiān)測(cè)的代碼詳解
這篇文章主要介紹了用云開發(fā)Cloudbase實(shí)現(xiàn)小程序多圖片內(nèi)容安全監(jiān)測(cè),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-06-06
12個(gè)非常實(shí)用的JavaScript小技巧【推薦】
下面小編就為大家?guī)硪黄?2個(gè)非常實(shí)用的JavaScript小技巧【推薦】。小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-05-05
JavaScript常見的跨標(biāo)簽頁通信方式總結(jié)
跨標(biāo)簽頁通信是指在瀏覽器中的不同標(biāo)簽頁之間進(jìn)行數(shù)據(jù)傳遞和通信的過程,這篇文章為大家整理了前端常見的跨標(biāo)簽頁通信方式,有需要的小伙伴可以了解下2023-10-10
JavaScript數(shù)據(jù)結(jié)構(gòu)與算法
這篇文章主要介紹了JavaScript數(shù)據(jù)結(jié)構(gòu)與算法,文章圍繞主題展開數(shù)據(jù)結(jié)構(gòu)與算法的概念,以及幾種常見的數(shù)據(jù)結(jié)構(gòu)是什么,有什么優(yōu)點(diǎn)和缺,具有一定的參考價(jià)值,需要的小伙伴可以參考一下2022-07-07
移動(dòng)端刮刮樂的實(shí)現(xiàn)方式(js+HTML5)
本篇文章主要介紹了移動(dòng)端刮刮樂的實(shí)現(xiàn)方法以及實(shí)現(xiàn)代碼。具有很好的參考價(jià)值。下面跟著小編一起來看下吧2017-03-03

