JavaScript实现求最大公共子串的方法


Posted in Javascript onFebruary 03, 2018

本文实例讲述了JavaScript实现求最大公共子串的方法。分享给大家供大家参考,具体如下:

求最大公共子串,常见的做法是使用矩阵。假设有字符串:abcdefg和字符串abcd,则可构成如下表所示矩阵。

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

对两个字符串的每一项都进行比较,若匹配则该项为1,不匹配则为0。然后求出对角线最长为1的那一段序列,即为最大公共子串。看上面的分开,似乎得使用二维数组了,在两个字符串都较大的情况下不是很划算,是否可以进一步优化?

可以,需要改变一下策略,如果该项匹配,则该项的值为再设为1,而是其对角线a[i-1, j-1](i > 1 && j > 1)的值+1,这样便可以只使用一个一维数组。

以一个字符串作为“行”,另一个作为“列”,比较两个字符串各项的值,用另外一个变量记录数组的最大值和字符串的起始位置。代码如下:

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);
}

但代码其实并不是最优的,为什么?因为上面的写法必须等待两层循环都完成。有没有相对更快一些的方法呢?

设有字符串a、b,其长度分别为len1、len2,其公共字子串一定是 <= Math.min(len1, len2),而且子串必定连续,且一定是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的长度,然后取较短的字符串作为。substr(idex, len),所以拿较短的串取其子串,然后判断它是否在较长的字符串中存在,如果存中则直接返回,否则再取下一位。

完整示例:

<!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>3water.com</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( "消耗时间:" + (getNow() - date) + "秒 " + LCS(s1, s2));
 date = getNow();
 alert( "消耗时间:" + (getNow() - date) + "秒 " + findMaxSubStr(s1, s2) );
 })();
function getNow() {
 return new Date().getTime();
}
</script>
 </body>
</html>

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
详谈javascript中DOM的基本属性
Feb 26 Javascript
javascript匀速运动实现方法分析
Jan 08 Javascript
微信小程序-图片、录音、音频播放、音乐播放、视频、文件代码实例
Nov 22 Javascript
Javascript基于jQuery UI实现选中区域拖拽效果
Nov 25 Javascript
判断jQuery是否加载完成,没完成继续判断的解决方法
Dec 06 jQuery
jQuery 获取除某指定对象外的其他对象 ( :not() 与.not())
Oct 10 jQuery
js拖动滑块和点击水波纹效果实例代码
Oct 16 Javascript
微信小程序云开发详细教程
May 16 Javascript
javascript实现简易数码时钟
Mar 30 Javascript
vue下canvas裁剪图片实例讲解
Apr 16 Javascript
vue自定义插件封装,实现简易的elementUi的Message和MessageBox的示例
Nov 20 Vue.js
JS中如何优雅的使用async await详解
Oct 05 Javascript
Node.js实现mysql连接池使用事务自动回收连接的方法示例
Feb 03 #Javascript
js删除数组中的元素delete和splice的区别详解
Feb 03 #Javascript
JS删除数组里的某个元素方法
Feb 03 #Javascript
jQuery niceScroll滚动条错位问题的解决方法
Feb 03 #jQuery
JS实现百度搜索接口及链接功能实例代码
Feb 02 #Javascript
原生JS实现的双色球功能示例
Feb 02 #Javascript
jQuery实现的下雪动画效果示例【附源码下载】
Feb 02 #jQuery
You might like
php相当简单的分页类
2008/10/02 PHP
PHP共享内存使用与信号控制实例分析
2018/05/09 PHP
PHP code 验证码生成类定义和简单使用示例
2020/05/27 PHP
Array.prototype 的泛型应用分析
2010/04/30 Javascript
js函数的引用, 关于内存的开销
2012/09/17 Javascript
js实现通用的微信分享组件示例
2014/03/10 Javascript
JavaScript 学习笔记之基础中的基础
2015/01/13 Javascript
Javascript毫秒数用法实例
2015/02/05 Javascript
JavaScript之数组(Array)详解
2015/04/01 Javascript
Bootstrap表单布局样式代码
2016/05/31 Javascript
jQuery自适应轮播图插件Swiper用法示例
2016/08/24 Javascript
chrome浏览器如何断点调试异步加载的JS
2016/09/05 Javascript
从0开始学Vue
2016/10/27 Javascript
node.js与C语言 实现遍历文件夹下最大的文件,并输出路径,大小
2017/01/20 Javascript
jQuery表格(Table)基本操作实例分析
2017/03/10 Javascript
NodeJS实现视频转码的示例代码
2017/11/18 NodeJs
JS中双击和单击事件冲突的解决方法
2018/04/09 Javascript
Vue2.0+Vux搭建一个完整的移动webApp项目的示例
2019/03/19 Javascript
react 组件传值的三种方法
2019/06/03 Javascript
js实现经典贪吃蛇小游戏
2020/03/19 Javascript
[01:07]2015国际邀请赛 中国区预选赛精彩回顾
2015/06/15 DOTA
python生成器generator用法实例分析
2015/06/04 Python
Python的Flask站点中集成xhEditor文本编辑器的教程
2016/06/13 Python
Python的语言类型(详解)
2017/06/24 Python
Python如何实现MySQL实例初始化详解
2017/11/06 Python
python 通过字符串调用对象属性或方法的实例讲解
2018/04/21 Python
python里运用私有属性和方法总结
2019/07/08 Python
python爬虫 基于requests模块的get请求实现详解
2019/08/20 Python
英国独特礼物想法和个性化礼物网站:notonthehighstreet.com
2018/04/16 全球购物
如何填写个人简历自我评价
2013/12/10 职场文书
2014年社会实践活动总结范文
2014/04/29 职场文书
党员服务承诺书
2014/05/28 职场文书
民族团结演讲稿范文
2014/08/27 职场文书
参观邀请函范文
2015/02/02 职场文书
python 逐步回归算法
2021/04/06 Python
SQLServer权限之只开启创建表权限
2022/04/12 SQL Server