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 相关文章推荐
Riot.js 快速的JavaScript单元测试框架
Nov 09 Javascript
javascript 三种方法实现获得和设置以及移除元素属性
Mar 20 Javascript
JavaScript的漂亮的代码片段
Jun 05 Javascript
laytpl 精致巧妙的JavaScript模板引擎
Aug 29 Javascript
html的DOM中Event对象onabort事件用法实例
Jan 21 Javascript
jQuery源码解读之hasClass()方法分析
Feb 20 Javascript
JQuery遍历元素的父辈和祖先的方法
Sep 18 Javascript
BootStrap 超链接变按钮的实现方法
Sep 25 Javascript
react-navigation 如何判断用户是否登录跳转到登录页的方法
Dec 01 Javascript
vue中v-model的应用及使用详解
Jun 27 Javascript
微信小程序项目实践之验证码倒计时功能
Jul 18 Javascript
vue 实现把路由单独分离出来
Aug 13 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
Netflix将与CLAMP、乙一以及冲方丁等6名知名制作人合伙展开原创动画计划!
2020/03/06 日漫
PHP常用代码大全(新手入门必备)
2010/06/29 PHP
php中判断字符串是否全是中文或含有中文的实现代码
2011/09/16 PHP
PHP随机字符串生成代码(包括大小写字母)
2013/06/24 PHP
PHP 实现页面静态化的几种方法
2017/07/23 PHP
jQuery 动画弹出窗体支持多种展现方式
2010/04/29 Javascript
使用时间戳解决ie缓存的问题
2014/08/20 Javascript
js简单的点击返回顶部效果实现方法
2015/04/10 Javascript
jquery实现左右滑动菜单效果代码
2015/08/27 Javascript
详解js中构造流程图的核心技术JsPlumb
2015/12/08 Javascript
深入浅析JavaScript面向对象和原型函数
2016/02/06 Javascript
JS实现iframe编辑器光标位置插入内容的方法(兼容IE和Firefox)
2016/06/24 Javascript
javascript 数组的正态分布排序的问题
2016/07/31 Javascript
js微信扫描二维码登录网站技术原理
2016/12/01 Javascript
利用Vue v-model实现一个自定义的表单组件
2017/04/27 Javascript
详解用webpack的CommonsChunkPlugin提取公共代码的3种方式
2017/11/09 Javascript
JS异步处理的进化史深入讲解
2019/08/25 Javascript
Vue项目中使用jsonp抓取跨域数据的方法
2019/11/10 Javascript
Vue使用虚拟dom进行渲染view的方法
2019/12/26 Javascript
详解Vue.js 响应接口
2020/07/04 Javascript
javascript实现简单留言板案例
2021/02/09 Javascript
python实现应用程序在右键菜单中添加打开方式功能
2017/01/09 Python
Python做简单的字符串匹配详解
2017/03/21 Python
pandas DataFrame创建方法的方式
2019/08/02 Python
python range实例用法分享
2020/02/06 Python
Python连接Hadoop数据中遇到的各种坑(汇总)
2020/04/14 Python
PyCharm设置Ipython交互环境和宏快捷键进行数据分析图文详解
2020/04/23 Python
python+appium+yaml移动端自动化测试框架实现详解
2020/11/24 Python
联想印度官方网上商店:Lenovo India
2019/08/24 全球购物
香港零食网购:上仓胃子
2020/06/08 全球购物
介绍一下SOA和SOA的基本特征
2016/02/24 面试题
网络工程专业自荐信范文
2014/03/16 职场文书
2014社会治安综合治理工作总结
2014/12/04 职场文书
php去除deprecated的实例方法
2021/11/17 PHP
Spring Cloud OpenFeign模版化客户端
2022/06/25 Java/Android
GO中sync包自由控制并发示例详解
2022/08/05 Golang