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 Event事件学习第一章 Event介绍
Feb 07 Javascript
JavaScript Event学习第十一章 按键的检测
Feb 10 Javascript
详解javascript事件冒泡
Jan 09 Javascript
JavaScript中获取HTML元素值的三种方法
Jun 20 Javascript
vue2.0开发实践总结之疑难篇
Dec 07 Javascript
Vue.use源码分析
Apr 22 Javascript
基于Vue.js 2.0实现百度搜索框效果
Dec 28 Javascript
AngularJS的$location使用方法详解
Oct 19 Javascript
Vue组件中slot的用法
Jan 30 Javascript
vue项目实现记住密码到cookie功能示例(附源码)
Jan 31 Javascript
详解JS判断页面是在手机端还是在PC端打开的方法
Apr 26 Javascript
详解ES6 CLASS在微信小程序中的应用实例
Apr 24 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桌面中心(四) 数据显示
2007/03/11 PHP
PHP脚本中include文件出错解决方法
2008/11/20 PHP
解决phpmyadmin中缺少mysqli扩展问题的方法
2013/05/06 PHP
PHP防盗链代码实例
2014/08/27 PHP
Laravel5.1数据库连接、创建数据库、创建model及创建控制器的方法
2016/03/29 PHP
jQuery.extend 函数的详细用法
2012/06/27 Javascript
JavaScript语言核心数据类型和变量使用介绍
2013/08/23 Javascript
JavaScript中的闭包(Closure)详细介绍
2014/12/30 Javascript
jquery左右全屏大尺寸多图滑动效果代码分享
2015/08/28 Javascript
详解JavaScript时间格式化
2015/12/23 Javascript
jquery实现表格中点击相应行变色功能效果【实例代码】
2016/05/09 Javascript
使用BootStrap和Metroui设计的metro风格微网站或手机app界面
2016/10/21 Javascript
微信小程序 scroll-view组件实现列表页实例代码
2016/12/14 Javascript
angularJs中datatable实现代码
2017/06/03 Javascript
Bootstrap模态框插入视频的实现代码
2017/06/25 Javascript
node.js通过axios实现网络请求的方法
2018/03/05 Javascript
Vue-cli打包后如何本地查看的操作
2020/09/02 Javascript
Handtrack.js库实现实时监测手部运动(推荐)
2021/02/08 Javascript
[06:23]2014DOTA2西雅图国际邀请赛 小组赛7月12日TOPPLAY
2014/07/12 DOTA
Python中MYSQLdb出现乱码的解决方法
2014/10/11 Python
python有证书的加密解密实现方法
2014/11/19 Python
Python实现可自定义大小的截屏功能
2018/01/20 Python
python实现屏保程序(适用于背单词)
2019/07/30 Python
python单例模式原理与创建方法实例分析
2019/10/26 Python
从numpy数组中取出满足条件的元素示例
2019/11/26 Python
python安装dlib库报错问题及解决方法
2020/03/16 Python
浅析python 定时拆分备份 nginx 日志的方法
2020/04/27 Python
pyqt5实现井字棋的示例代码
2020/12/07 Python
Free People中国官网:波西米亚风格女装服饰
2016/08/30 全球购物
如何打印出当前源文件的文件名以及源文件的当前行号
2015/04/05 面试题
医学生求职信
2014/07/01 职场文书
2014年体育工作总结
2014/11/24 职场文书
酒店优秀员工推荐信
2015/03/24 职场文书
《地震中的父与子》教学反思
2016/02/16 职场文书
个人工作总结怎么写?
2019/04/09 职场文书
javascript数组includes、reduce的基本使用
2021/07/02 Javascript