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 相关文章推荐
编写自己的jQuery提示框(Tip)插件
Feb 05 Javascript
JavaScript使用Replace进行字符串替换的方法
Apr 14 Javascript
Js实现无刷新删除内容
Apr 29 Javascript
AngularJS表格详解及示例代码
Aug 17 Javascript
jQuery监听文件上传实现进度条效果的方法
Oct 16 Javascript
js+css3实现旋转效果
Jan 20 Javascript
AngularJS读取JSON及XML文件的方法示例
May 25 Javascript
深入浅出webpack教程系列_安装与基本打包用法和命令参数详解
Sep 10 Javascript
微信小程序wx.previewImage预览图片实例详解
Dec 07 Javascript
jQuery实现王者荣耀手风琴效果
Jan 17 jQuery
鸿蒙系统中的 JS 开发框架
Sep 18 Javascript
vue中控制mock在开发环境使用,在生产环境禁用方式
Apr 06 Vue.js
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(1) php开发环境配置
2010/02/15 PHP
PHP中如何判断exec函数执行成功?
2016/08/04 PHP
JavaScript栏目列表隐藏/显示简单实现
2013/04/03 Javascript
ie与ff下的event事件使用介绍
2013/11/25 Javascript
jquery中val()方法是从最后一个选项往前读取的
2015/09/06 Javascript
实例解析jQuery工具函数
2016/12/01 Javascript
深入理解jquery的$.extend()、$.fn和$.fn.extend()
2017/07/08 jQuery
JS 中使用Promise 实现红绿灯实例代码(demo)
2017/10/20 Javascript
vue实现验证码输入框组件
2017/12/14 Javascript
Vue的事件响应式进度条组件实例详解
2018/02/04 Javascript
使用Vue开发动态刷新Echarts组件的教程详解
2018/03/22 Javascript
Bootstrap导航菜单点击后无法自动添加active的处理方法
2018/08/10 Javascript
基于vue开发微信小程序mpvue-docs跳转页面功能
2019/04/10 Javascript
React精髓!一篇全概括小结(急速)
2019/05/23 Javascript
js实现表格数据搜索
2020/08/09 Javascript
[01:38]完美世界DOTA2联赛PWL S3 集锦第四期
2020/12/21 DOTA
浅谈Matplotlib简介和pyplot的简单使用——文本标注和箭头
2018/01/09 Python
django2+uwsgi+nginx上线部署到服务器Ubuntu16.04
2018/06/26 Python
用Python将mysql数据导出成json的方法
2018/08/21 Python
python基于socket进行端口转发实现后门隐藏的示例
2019/07/25 Python
详解Python在使用JSON时需要注意的编码问题
2019/12/06 Python
使用CSS3制作倾斜导航条和毛玻璃效果
2017/09/12 HTML / CSS
HTML5 Canvas基本线条绘制的实例教程
2016/03/17 HTML / CSS
HTML5无刷新改变当前url的代码
2017/03/15 HTML / CSS
HTML5 播放 RTSP 视频的实例代码
2019/07/29 HTML / CSS
纽约的奢华内衣店:Journelle
2016/07/29 全球购物
在线购买澳大利亚设计师手拿包和奢华晚装手袋:Olga Berg
2019/03/20 全球购物
在对linux系统分区进行格式化时需要对磁盘簇(或i节点密度)的大小进行选择,请说明选择的原则
2012/11/24 面试题
技术总监管理职责范本
2014/03/06 职场文书
大学生村官个人对照检查材料(群众路线)
2014/09/26 职场文书
2015年简历自我评价范文
2015/03/11 职场文书
通知的写法
2015/04/23 职场文书
大学毕业典礼致辞
2015/07/29 职场文书
2016年第32个教师节致辞
2015/11/26 职场文书
vue实现简单数据双向绑定
2021/04/28 Vue.js
Hive常用日期格式转换语法
2022/06/25 数据库