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 相关文章推荐
修改js Calendar日历控件 兼容IE9/谷歌/火狐
Jan 04 Javascript
15条JavaScript最佳实践小结
Aug 09 Javascript
javascript操作css属性
Dec 30 Javascript
JavaScript生成福利彩票双色球号码
May 15 Javascript
在jQuery中处理XML数据的大致方法
Aug 14 Javascript
json定义及jquery操作json的方法
Oct 03 Javascript
webuploader模态框ueditor显示问题解决方法
Dec 27 Javascript
js实现带进度条提示的多视频上传功能
Dec 13 Javascript
seajs中最常用的7个功能、配置示例
Oct 10 Javascript
详解vue中async-await的使用误区
Dec 05 Javascript
vue - vue.config.js中devServer配置方式
Oct 30 Javascript
json解析大全 双引号、键值对不在一起的情况
Dec 06 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伪造referer实例代码
2008/09/20 PHP
yii2中使用Active Record模式的方法
2016/01/09 PHP
php使用正则验证中文
2016/04/06 PHP
PHP入门教程之PHP操作MySQL的方法分析
2016/09/11 PHP
PHP Header用于页面跳转时的几个注意事项
2016/10/21 PHP
php用wangeditor3实现图片上传功能
2019/08/22 PHP
jQuery中文入门指南,翻译加实例,jQuery的起点教程
2007/02/09 Javascript
WEB高性能开发之疯狂的HTML压缩
2010/06/19 Javascript
JS基于面向对象实现的放烟花效果
2015/05/07 Javascript
AngularJS ng-controller 指令简单实例
2016/08/01 Javascript
JavaScript数组_动力节点Java学院整理
2017/06/26 Javascript
node内置调试方法总结
2018/02/22 Javascript
element-ui 表格实现单元格可编辑的示例
2018/02/26 Javascript
vue 注册组件的使用详解
2018/05/05 Javascript
vue中使用better-scroll实现滑动效果及注意事项
2018/11/15 Javascript
利用node 判断打开的是文件 还是 文件夹的实例
2019/06/10 Javascript
浅谈Vue3.0新版API之composition-api入坑指南
2020/04/30 Javascript
JavaScript实现简单的弹窗效果
2020/05/19 Javascript
Express 配置HTML页面访问的实现
2020/11/01 Javascript
python读取TXT每行,并存到LIST中的方法
2018/10/26 Python
Django如何开发简单的查询接口详解
2019/05/17 Python
用Python实现BP神经网络(附代码)
2019/07/10 Python
python实现根据文件格式分类
2019/10/31 Python
Python+opencv+pyaudio实现带声音屏幕录制
2019/12/23 Python
Python使用pdb调试代码的技巧
2020/05/03 Python
Python字符串三种格式化输出
2020/09/17 Python
将SVG图引入到HTML页面的实现
2019/09/20 HTML / CSS
大学生写自荐信的技巧
2014/01/08 职场文书
新三好学生主要事迹
2014/01/23 职场文书
医学生个人求职信范文
2014/02/07 职场文书
云台山导游词
2015/02/03 职场文书
2015年幼儿园保育员工作总结
2015/04/23 职场文书
军训结束新闻稿
2015/07/17 职场文书
HTML页面滚动时部分内容位置固定不滚动的实现
2021/04/14 HTML / CSS
python 爬取哔哩哔哩up主信息和投稿视频
2021/06/07 Python
Oracle 11g数据库使用expdp每周进行数据备份并上传到备份服务器
2022/06/28 Oracle