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 相关文章推荐
用JavaScrpt实现文件夹简单轻松加密的实现方法图文
Sep 08 Javascript
JQuery实现table行折叠效果以JSON做数据源
May 26 Javascript
jquery实现点击label的同时触发文本框点击事件的方法
Jun 05 Javascript
数据分析软件之FineReport教程:[5]参数界面JS(全)
Aug 13 Javascript
javascript 使用for循环时该注意的问题-附问题总结
Aug 19 Javascript
Node.js DES加密的简单实现
Jul 07 Javascript
javascript中Date对象应用之简易日历实现
Jul 12 Javascript
利用jQuery插件imgAreaSelect实现获得选择域的图像信息
Dec 02 Javascript
js闭包用法实例详解
Dec 13 Javascript
Node.js数据库操作之查询MySQL数据库(二)
Mar 04 Javascript
AngularJS 教程及实例代码
Oct 23 Javascript
JavaScript大数相加相乘的实现方法实例
Oct 18 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
第九节--绑定
2006/11/16 PHP
php实现过滤UBB代码的类
2015/03/12 PHP
php实现的xml操作类
2016/01/15 PHP
关于javascript 回调函数中变量作用域的讨论
2009/09/11 Javascript
jquery ajax 同步异步的执行示例代码
2010/06/23 Javascript
javascript中最常用的继承模式 组合继承
2010/08/12 Javascript
一个简单的Ext.XTemplate的实例代码
2012/03/18 Javascript
Javascript实现页面跳转的几种方式分享
2013/10/26 Javascript
探讨js中的双感叹号判断
2013/11/11 Javascript
Extjs4中的分页应用结合前后台
2013/12/13 Javascript
js的image onload事件使用遇到的问题
2014/07/15 Javascript
JavaScript监听文本框回车事件并过滤文本框空格的方法
2015/04/16 Javascript
js滚动条平滑移动示例代码
2016/03/29 Javascript
AngularJS 2.0入门权威指南
2016/10/08 Javascript
JS实现倒计时(天数、时、分、秒)
2016/11/16 Javascript
d3.js中冷门却实用的内置函数总结
2017/02/04 Javascript
详解微信小程序 相对定位和绝对定位
2017/05/11 Javascript
Vue.js实现在下拉列表区域外点击即可关闭下拉列表的功能(自定义下拉列表)
2017/05/30 Javascript
Angular2里获取(input file)上传文件的内容的方法
2017/09/05 Javascript
vue 页面加载进度条组件实例
2018/02/05 Javascript
Vue使用高德地图搭建实时公交应用功能(地图 + 附近站点+线路详情 + 输入提示+换乘详情)
2018/05/16 Javascript
AngularJs的UI组件ui-Bootstrap之Tooltip和Popover
2018/07/13 Javascript
使用Nuxt.js改造已有项目的方法
2018/08/07 Javascript
axios封装,使用拦截器统一处理接口,超详细的教程(推荐)
2019/05/02 Javascript
javascript设计模式 ? 享元模式原理与用法实例分析
2020/04/15 Javascript
解决vscode进行vue格式化,会自动补分号和双引号的问题
2020/10/26 Javascript
Python实现自动为照片添加日期并分类的方法
2017/09/30 Python
Python+OpenCV让电脑帮你玩微信跳一跳
2018/01/04 Python
Python+matplotlib实现华丽的文本框演示代码
2018/01/22 Python
python plotly绘制直方图实例详解
2019/07/22 Python
中秋手机店促销方案
2014/06/16 职场文书
南湾猴岛导游词
2015/02/09 职场文书
四大名著读书笔记
2015/06/25 职场文书
oracle通过存储过程上传list保存功能
2021/05/12 Oracle
python scrapy简单模拟登录的代码分析
2021/07/21 Python
SpringBoot集成Redis的思路详解
2021/10/16 Redis