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仿php的print_r函数输出json数据
Sep 13 Javascript
JavaScript中实现异步编程模式的4种方法
Sep 24 Javascript
jQuery实现为图片添加镜头放大效果的方法
Jun 25 Javascript
jQuery插件windowScroll实现单屏滚动特效
Jul 14 Javascript
js仿百度登录页实现拖动窗口效果
Mar 11 Javascript
20分钟轻松创建自己的Bootstrap站点
May 12 Javascript
jQuery Easyui datagrid行内实现【添加】、【编辑】、【上移】、【下移】
Dec 19 Javascript
微信小程序 地图map实例详解
Jun 07 Javascript
如何编写一个完整的Angular4 FormText 组件
Nov 18 Javascript
Angular实现双向折叠列表组件的示例代码
Nov 21 Javascript
Nuxt.js实现一个SSR的前端博客的示例代码
Sep 06 Javascript
vue项目实现多语言切换的思路
Sep 17 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
destoon实现调用图文新闻的方法
2014/08/21 PHP
PHP生成图片缩略图类示例
2017/01/12 PHP
yii2.0整合阿里云oss上传单个文件的示例
2017/09/19 PHP
PHP简单实现记录网站访问量功能示例
2018/06/06 PHP
Javascript实现的分页函数
2007/02/07 Javascript
jquery animate实现鼠标放上去显示离开隐藏效果
2013/07/21 Javascript
Enter回车切换输入焦点实现思路与代码兼容各大浏览器
2014/09/01 Javascript
一个JavaScript函数把URL参数解析成Json对象
2014/09/24 Javascript
javascript中通过arguments参数伪装方法重载
2014/10/08 Javascript
js获取所有checkbox的值的简单实例
2016/05/30 Javascript
jQuery animate()实现背景色渐变效果的处理方法【使用jQuery.color.js插件】
2017/03/15 Javascript
使用Xcache缓存器加速PHP网站的配置方法
2017/04/22 Javascript
vue-cli项目优化方法- 缩短首屏加载时间
2018/04/01 Javascript
详解基于原生JS验证表单组件xy-form
2019/08/20 Javascript
javascript使用链接跨域下载图片
2019/11/01 Javascript
gearman的安装启动及python API使用实例
2014/07/08 Python
Python的ORM框架中SQLAlchemy库的查询操作的教程
2015/04/25 Python
Python判断Abundant Number的方法
2015/06/15 Python
python实现键盘输入的实操方法
2019/07/16 Python
Python 进程之间共享数据(全局变量)的方法
2019/07/16 Python
pycharm2020.2 配置使用的方法详解
2020/09/16 Python
详解Css3新特性应用之过渡与动画
2017/01/10 HTML / CSS
基于HTML5超酷摄像头(HTML5 webcam)拍照功能实现代码
2012/12/13 HTML / CSS
为智能设备设计个性化保护套网站:caseable
2017/01/05 全球购物
澳大利亚首个在线预订旅游网站:Wotif
2017/07/19 全球购物
巴西电子、家电、智能手机购物网站:Girafa
2019/06/04 全球购物
请介绍一下Ant
2016/07/22 面试题
毕业生的求职信范文分享
2013/12/04 职场文书
学生实习证明范文
2014/09/28 职场文书
国庆横幅标语
2014/10/08 职场文书
2014年人事部工作总结
2014/12/03 职场文书
学校重阳节活动总结
2015/03/24 职场文书
离职信范本
2015/06/23 职场文书
2016小学新学期寄语
2015/12/04 职场文书
解决vue自定义组件@click点击失效问题
2022/04/30 Vue.js
关于windows server 2012 DC 环境 重启后蓝屏代码:0xc00002e2的问题
2022/05/25 Servers