免费刷金币,请点击这里
TE社区 > 前端技术
客服QQ:1206116161

JavaScript中数据结构与算法(五):经典KMP算法

fgffgfg 于 2018-03-29 10:00:35 创建话题
(2)
(0)
举报

KMP算法和BM算法

KMP是前缀匹配和BM后缀匹配的经典算法,看得出来前缀匹配和后缀匹配的区别就仅仅在于比较的顺序不同

前缀匹配是指:模式串和母串的比较从左到右,模式串的移动也是从 左到右

后缀匹配是指:模式串和母串的的比较从右到左,模式串的移动从左到右。

通过上一章显而易见BF算法也是属于前缀的算法,不过就非常霸蛮的逐个匹配的效率自然不用提了O(mn),网上蛋疼的KMP是讲解很多,基本都是走的高大上路线看的你也是一头雾水,我试图用自己的理解用最接地气的方式描述

KMP

KMP也是一种优化版的前缀算法,之所以叫KMP就是Knuth、Morris、Pratt三个人名的缩写,对比下BF那么KMP的算法的优化点就在“每次往后移动的距离”它会动态的调整每次模式串的移动距离,BF是每次都+1,

KMP则不一定

如图BF与KMP前置算法的区别对比

我通过图对比我们发现:

在文本串T中搜索模式串P,在自然匹配第6个字母c的时候发现二等不一致了,那么BF的方法,就是把整个模式串P移动一位,KMP则是移动二位.

BF的匹配方法我们是知道的,但是KMP为什么会移动二位,而不是一位或者三位四位呢?

这就上一张图我们讲解下,模式串P在匹配了ababa的时候都是正确的,当到c的时候才是错误,那么KMP算法的想法是:ababa是正确的匹配完成的信息,我们能不能利用这个信息,不要把"搜索位置"移回已经比较过的位置,继续把它向后移,这样就提高了效率。

那么问题来了, 我怎么知道要移动多少个位置?

这个偏移的算法KMP的作者们就给我们总结好了:

代码如下:

移动位数 = 已匹配的字符数 - 对应的部分匹配值

偏移算法只跟子串有关系,没文本串没毛线关系,所以这里需要特别注意了

那么我们怎么理解子串中已匹配的字符数与对应的部分匹配值?

已匹配的字符:

代码如下:

T : abababaabab
p : ababacb

p中红色的标记就是已经匹配的字符,这个很好理解

部分匹配值:

这个就是核心的算法了,也是比较难于理解的

假如:

代码如下:

T:aaronaabbcc
P:aaronaac

我们可以观察这个文本如果我们在匹配c的时候出错,我们下一个移动的位置就上个的结构来讲,移动到那里最合理?
代码如下:

aaronaabbcc
     aaronaac

那么就是说:在模式文本内部,某一段字符头尾都一样,那么自然过滤的时候可以跳过这一段内容了,这个思路也是合理的

 

知道了这个规律,那么给出来的部分匹配表算法如下:

首先,要了解两个概念:"前缀"和"后缀"。 "前缀"指除了最后一个字符以外,一个字符串的全部头部组合;"后缀"指除了第一个字符以外,一个字符串的全部尾部组合。

"部分匹配值"就是"前缀"和"后缀"的最长的共有元素的长度”

我们看看aaronaac的如果是BF匹配的时候划分是这样的

BF的位移: a,aa,aar,aaro,aaron,aarona,aaronaa,aaronaac

那么KMP的划分呢?这里就要引入前缀与后缀了

我们先看看KMP部分匹配表的结果是这样的:

代码如下:

a   a  r  o  n  a  a  c
[0, 1, 0, 0, 0, 1, 2, 0]

肯定是一头雾水,不急我们分解下,前缀与后缀

代码如下:

匹配字符串 :“Aaron”
前缀:A,Aa, Aar ,Aaro
后缀:aron,ron,on,n

移动的位置:其实就是针对每一个已匹配的字符做前缀与后缀的对比是否相等,然后算出共有的长度

部分匹配表的分解

KMP中的匹配表的算法,其中p表示前缀,n表示后缀,r表示结果

代码如下:

a,         p=>0, n=>0  r = 0

aa,        p=>[a],n=>[a] , r = a.length => 1

aar,       p=>[a,aa], n=>[r,ar]  ,r = 0

aaro,      p=>[a,aa,aar], n=>[o,ra,aro] ,r = 0

aaron      p=>[a,aa,aar,aaro], n=>[n,on,ron,aron] ,r = 0

aarona,    p=>[a,aa,aar,aaro,aaron], n=>[a,na,ona,rona,arona] ,r = a.lenght = 1

aaronaa,   p=>[a,aa,aar,aaro,aaron,aarona], n=>[a,aa,naa,onaa,ronaa,aronaa] ,  r = Math.max(a.length,aa.length) = 2

aaronaac   p=>[a,aa,aar,aaro,aaron,aarona], n=>[c,ac,aac,naac,onaac,ronaac]  r = 0

类似BF算法一下,先分解每一次可能匹配的下标的位置先缓存起来,在匹配的时候通过这个《部分匹配表》来定位需要后移动的位数

所以最后aaronaac的匹配表的结果 0,1,0,0,0,1,2,0 就是这么来的

下面将会实现JS版的KMP,有2种

KMP实现(一):缓存匹配表的KMP

KMP实现(二):动态计算next的KMP


KMP实现(一)

匹配表

KMP算法中最重要的就是匹配表,如果不要匹配表那就是BF的实现,加上匹配表就是KMP了

匹配表决定了next下一个位移的计数

针对上面匹配表的规律,我们设计一个kmpGetStrPartMatchValue的方法

function kmpGetStrPartMatchValue(str) {
   var prefix = [];
   var suffix = [];
   var partMatch = [];
   for (var i = 0, j = str.length; i < j; i++) {
    var newStr = str.substring(0, i + 1);
    if (newStr.length == 1) {
     partMatch[i] = 0;
    } else {
     for (var k = 0; k < i; k++) {
      //前缀
      prefix[k] = newStr.slice(0, k + 1);
      //后缀
      suffix[k] = newStr.slice(-k - 1);
      //如果相等就计算大小,并放入结果集中
      if (prefix[k] == suffix[k]) {
       partMatch[i] = prefix[k].length;
      }
     }
     if (!partMatch[i]) {
      partMatch[i] = 0;
     }
    }
   }
   return partMatch;
  }

完全按照KMP中的匹配表的算法的实现,通过str.substring(0, i + 1) 分解a->aa->aar->aaro->aaron->aarona->aaronaa-aaronaac

然后在每一个分解中通过前缀后缀算出共有元素的长度

回退算法

KMP也是前置算法,完全可以把BF那一套搬过来,唯一修改的地方就是BF回溯的时候直接是加1,KMP在回溯的时候我们就通过匹配表算出这个next值即可

//子循环
for (var j = 0; j < searchLength; j++) {
  //如果与主串匹配
  if (searchStr.charAt(j) == sourceStr.charAt(i)) {
    //如果是匹配完成
    if (j == searchLength - 1) {
     result = i - j;
     break;
    } else {
     //如果匹配到了,就继续循环,i++是用来增加主串的下标位
     i++;
    }
  } else {
   //在子串的匹配中i是被叠加了
   if (j > 1 && part[j - 1] > 0) {
    i += (i - j - part[j - 1]);
   } else {
    //移动一位
    i = (i - j)
   }
   break;
  }
}

红色标记的就是KMP的核心点 next的值  = 已匹配的字符数 - 对应的部分匹配值

完整的KMP算法

<!doctype html><div id="test2"><div><script type="text/javascript">
 

  function kmpGetStrPartMatchValue(str) {
   var prefix = [];
   var suffix = [];
   var partMatch = [];
   for (var i = 0, j = str.length; i < j; i++) {
    var newStr = str.substring(0, i + 1);
    if (newStr.length == 1) {
     partMatch[i] = 0;
    } else {
     for (var k = 0; k < i; k++) {
      //取前缀
      prefix[k] = newStr.slice(0, k + 1);
      suffix[k] = newStr.slice(-k - 1);
      if (prefix[k] == suffix[k]) {
       partMatch[i] = prefix[k].length;
      }
     }
     if (!partMatch[i]) {
      partMatch[i] = 0;
     }
    }
   }
   return partMatch;
  }



function KMP(sourceStr, searchStr) {
  //生成匹配表
  var part     = kmpGetStrPartMatchValue(searchStr);
  var sourceLength = sourceStr.length;
  var searchLength = searchStr.length;
  var result;
  var i = 0;
  var j = 0;

  for (; i < sourceStr.length; i++) { //最外层循环,主串

    //子循环
    for (var j = 0; j < searchLength; j++) {
      //如果与主串匹配
      if (searchStr.charAt(j) == sourceStr.charAt(i)) {
        //如果是匹配完成
        if (j == searchLength - 1) {
         result = i - j;
         break;
        } else {
         //如果匹配到了,就继续循环,i++是用来增加主串的下标位
         i++;
        }
      } else {
       //在子串的匹配中i是被叠加了
       if (j > 1 && part[j - 1] > 0) {
        i += (i - j - part[j - 1]);
       } else {
        //移动一位
        i = (i - j)
       }
       break;
      }
    }

    if (result || result == 0) {
     break;
    }
  }


  if (result || result == 0) {
   return result
  } else {
   return -1;
  }
}

 var s = "BBC ABCDAB ABCDABCDABDE";
 var t = "ABCDABD";


 show('indexOf',function() {
  return s.indexOf(t)
 })

 show('KMP',function() {
  return KMP(s,t)
 })

 function show(bf_name,fn) {
  var myDate = +new Date()
  var r = fn();
  var div = document.createElement('div')
  div.innerHTML = bf_name +'算法,搜索位置:' + r + ",耗时" + (+new Date() - myDate) + "ms";
   document.getElementById("test2").appendChild(div);
 }


</script></div></div>

KMP(二)

第一种kmp的算法很明显,是通过缓存查找匹配表也就是常见的空间换时间了。那么另一种就是时时查找的算法,通过传递一个具体的完成字符串,算出这个匹配值出来,原理都一样

生成缓存表的时候是整体全部算出来的,我们现在等于只要挑其中的一条就可以了,那么只要算法定位到当然的匹配即可

next算法

function next(str) {
  var prefix = [];
  var suffix = [];
  var partMatch;
  var i = str.length
  var newStr = str.substring(0, i + 1);
  for (var k = 0; k < i; k++) {
   //取前缀
   prefix[k] = newStr.slice(0, k + 1);
   suffix[k] = newStr.slice(-k - 1);
   if (prefix[k] == suffix[k]) {
    partMatch = prefix[k].length;
   }
  }
  if (!partMatch) {
   partMatch = 0;
  }
  return partMatch;
}

其实跟匹配表是一样的,去掉了循环直接定位到当前已成功匹配的串了

完整的KMP.next算法

<!doctype html><div id="testnext"><div><script type="text/javascript">
 
  function next(str) {
    var prefix = [];
    var suffix = [];
    var partMatch;
    var i = str.length
    var newStr = str.substring(0, i + 1);
    for (var k = 0; k < i; k++) {
     //取前缀
     prefix[k] = newStr.slice(0, k + 1);
     suffix[k] = newStr.slice(-k - 1);
     if (prefix[k] == suffix[k]) {
      partMatch = prefix[k].length;
     }
    }
    if (!partMatch) {
     partMatch = 0;
    }
    return partMatch;
  }

  function KMP(sourceStr, searchStr) {
    var sourceLength = sourceStr.length;
    var searchLength = searchStr.length;
    var result;
    var i = 0;
    var j = 0;

    for (; i < sourceStr.length; i++) { //最外层循环,主串

      //子循环
      for (var j = 0; j < searchLength; j++) {
        //如果与主串匹配
        if (searchStr.charAt(j) == sourceStr.charAt(i)) {
          //如果是匹配完成
          if (j == searchLength - 1) {
           result = i - j;
           break;
          } else {
           //如果匹配到了,就继续循环,i++是用来增加主串的下标位
           i++;
          }
        } else {
         if (j > 1) {
          i += i - next(searchStr.slice(0,j));
         } else {
          //移动一位
          i = (i - j)
         }
         break;
        }
      }

      if (result || result == 0) {
       break;
      }
    }


    if (result || result == 0) {
     return result
    } else {
     return -1;
    }
  }

 var s = "BBC ABCDAB ABCDABCDABDE";
 var t = "ABCDAB";


  show('indexOf',function() {
   return s.indexOf(t)
  })

  show('KMP.next',function() {
   return KMP(s,t)
  })

  function show(bf_name,fn) {
   var myDate = +new Date()
   var r = fn();
   var div = document.createElement('div')
   div.innerHTML = bf_name +'算法,搜索位置:' + r + ",耗时" + (+new Date() - myDate) + "ms";
    document.getElementById("testnext").appendChild(div);
  }

</script></div></div>

git代码下载: https://github.com/JsAaron/data_structure

扫码关注TE官方微博 扫码关注TE官方微博
Python爬虫实例_城市公交网络站点数据的爬取方法 如何获取网站icon有哪些可行的方法 JavaScript 对象链式操作测试代码 javascript jscroll模拟html元素滚动条 dedecms实现大图showphoto.htm输出图集内容简介方法 全面解析Bootstrap表单使用方法(表单样式) 初探Swift3.0带来的变化汇总 jQueryUI Sortable 应用Demo(分享) 30个mysql千万级大数据SQL查询优化技巧详解 ajax初级教程之获取博文列表 domReady的实现案例 基于jQuery实现Accordion手风琴自定义插件 一个奇葩的最短的 IE 版本判断JS脚本 checkbox click事件触发span元素内容改变的方法 基于JS实现回到页面顶部的五种写法(从实现到增强) 数据库 三范式最简单最易记的解释 JavaScript使用原型和原型链实现对象继承的方法详解 JavaScript实现的浏览器下载文件的方法 SignalR Self Host+MVC等多端消息推送服务(二) IOS如何在Host App 与 App Extension 之间发送通知 Nodejs如何搭建Web服务器 PHP下载远程图片并保存到本地方法总结 .NET中STAThread的使用详解 php中html_entity_decode实现HTML实体转义 PHP支持多种格式图片上传(支持jpg、png、gif) js 原生判断内容区域是否滚动到底部的实例代码 Bootstrap对话框使用实例讲解 Javascript使用SWFUpload进行多文件上传 Bootstrap3使用typeahead插件实现自动补全功能 详解Linux中Nginx反向代理下的tomcat集群 Bootstrap modal使用及点击外部不消失的解决方法 javascript学习总结之js使用技巧 Html5游戏开发之乒乓Ping Pong游戏示例(二) oracle11g 通过修改配置文件方式连接远程数据库的方法 jquery判断当前浏览器的实现代码 JavaScript中读取和保存文件实例 使用CSS禁止textarea调整大小功能的方法 CSS中使用image data URI来处理图片的方法 mysql installer community 8.0.12.0安装图文教程 浅谈Transact-SQL 详解用Redis实现Session功能 不容小觑的十大互联网恶意软件 jQuery基于Ajax实现读取XML数据功能示例 Android 使用AsyncTask实现断点续传 Yii2使用驼峰命名的形式访问控制器(实例讲解) javascript动画之圆形运动,环绕鼠标运动作小球 处理驱动器和文件夹 基于jQuery的简单九宫格实现代码 angular2系列之路由转场动画的示例代码 SqlServer高版本数据备份还原到低版本 javascript smipleChart 简单图标类 简单模拟node.js中require的加载机制 javascript动态修改Li节点值的方法 jQuery中的Deferred和promise 的区别 serif和sans serif:西方国家的字母体系 js确认删除对话框适用于a标签及submit JavaScript实现对下拉列表值进行排序的方法 分享20款美化网站的 jQuery Lightbox 灯箱插件 JS实现禁止鼠标右键的功能 苹果Mac HDMI没声音现象的原因及解决方法介绍 将博客迁移至docker纪实 Ajax 通过城市名获取数据(全国天气预报API) JavaScript字符串对象substr方法入门实例(用于截取字符串) rudy 重载方法 详解 jquery.cvtooltip.js 基于jquery的气泡提示插件 CentOS6.9下mysql 5.7.17安装配置方法图文教程 jQuery中before()方法用法实例 python实现每次处理一个字符的三种方法 JS实现拖动滚动条评分的效果代码分享 PowerShell小技巧之获取TCP响应(类Telnet) python实现简单神经网络算法 JavaScript统计字符串中每个字符出现次数完整实例 Linux系统下查找安装包所在目录的方法汇总 轻松实现 CKfinder进驻CKEditor3.0 javascript生成大小写字母 Python元组操作实例分析【创建、赋值、更新、删除等】 Python实现多条件筛选目标数据功能【测试可用】 jquery 实时监听输入框值变化的完美方法(必看) Linux中安装sosreport和supportconfig来收集系统信息 JS实现用特殊符号替换字符串的中间部分区域的实例代码 JS实现获取键盘按下的按键并显示在页面上的方法 深入解析Python中的descriptor描述器的作用及用法 Python实现过滤单个Android程序日志脚本分享 jquery实现两边飘浮可关闭的对联广告 Angular4学习笔记之实现绑定和分包 不得不看之JavaScript构造函数及new运算符 MySql使用skip-name-resolve解决外网链接客户端过慢问题 IE6,IE7浏览器下 margin 无效的解决方法 Oracle数据库表名支持的最大长度是多少 jQuery中Form相关知识汇总 asp.net更新指定记录的方法 eregi_replace与preg_replace 函数代码的用法比较 JavaScript 放大镜 放大倍率和视窗尺寸 JavaScript数据存储 Cookie篇 javascript 学习之旅 (1) 在Nginx上部署ThinkPHP项目教程 MAC系统Apple ID如何充值以便下载需要的APP Mongodb 3.2.9开启用户权限认证问题的步骤详解 js实现动态改变字体大小代码 浅析PHP substr,mb_substr以及mb_strcut的区别和用法 javascript自动恢复文本框点击清除后的默认文本 纯CSS3实现带动画效果导航菜单无需js jQuery Ajax 全局调用封装实例代码详解 CSS3实现多背景展示效果通过CSS3定位多张背景 Ruby初学笔记之Hello World 从刷票了解获得客户端IP的方法 dedecms登陆后台直接转跳到首页解决办法 JSP实用教程之简易文件上传组件的实现方法(附源码) Android UI控件之ImageSwitcher实现图片切换效果 Python实现压缩与解压gzip大文件的方法 讲解Python中for循环下的索引变量的作用域 ASP基础入门第九篇(Global.asa文件的使用) 纯JS实现动态时间显示代码 javaScript中封装的各种写法示例(推荐) Bootstrap前端开发案例一 asp中让function同时返回多个值的代码 js类型检查实现代码 JQUERY设置IFRAME的SRC值的代码 js_jquery判断浏览器的方法小结 Java进阶 JNI使用技巧点滴 jquery插件开发之实现md5插件 JavaScript模板入门介绍 jquery 回车事件实现代码 .NET Core系列之MemoryCache 缓存域 python正则表达式的使用 CSS设置div对象盒子里部分文字加粗的实例介绍 php简单解析mysqli查询结果的方法(2种方法) JavaScript解析json格式数据简单示例 Vue2单一事件管理组件通信 浅谈Django的缓存机制 python Django批量导入不重复数据 MongoDB修改、删除文档的域属性实例 PHP中strtr字符串替换用法详解 Vue封装一个简单轻量的上传文件组件的示例 Centos 6.4源码安装mysql-5.6.28.tar.gz教程 javascript判断图片是否加载完成的方法推荐 js实现div闪烁原理及实现代码 PHP_Javascript_CSS_jQuery常用知识大全详细整理第1_2页 javascript Event对象详解及使用示例 Angular-Touch库用法示例 ASP.NET中相对路径的使用总结 Python实现时钟显示效果思路详解 jQuery拖拽插件gridster使用指南 js创建对象的几种常用方式小结(推荐) Python实现控制台中的进度条功能代码 sql server创建临时表的两种写法和删除临时表 php建立Ftp连接的方法 jcarousellite.js 基于Jquery的图片无缝滚动插件 windows下mysql数据库主从配置教程 MongoDB中MapReduce编程模型使用实例 DB2编程序技巧 (十) jQuery实现的调整表格行tr上下顺序 针对distinct疑问引发的一系列思考 jQuery实现仿新浪微博浮动的消息提示框(可智能定位) jquery实现简单实用的轮播器 php使HTML标签自动补全闭合函数代码 JSP的9种基本内置组件 Ajax+Asp源代码]读取数据库内容的表格(没有用框架)第1_2页 JS实现仿新浪黄色经典滑动门效果代码 DedeCms V5.3 终极性能优化策略 详解使用docker 1.12 搭建多主机docker swarm集群 ASP.NET MVC用存储过程批量添加修改数据操作 HTML5注册页面示例代码 浅谈Angular路由复用策略 JavaScript对象之深度克隆介绍 SQL Server Alert发送告警邮件少了的原因 css与javascript跨浏览器兼容性总结 javascript的函数、创建对象、封装、属性和方法、继承 为开发者准备的10款最好的jQuery日历插件 ASP强制刷新网页和判断文件地址实例代码 js + css实现标签内容切换功能(实例讲解) 利用Redis实现SQL伸缩的方法 jQuery如何使用自动触发事件trigger JavaScript实现的图像模糊算法代码分享 Python数据结构与算法之图的广度优先与深度优先搜索算法示例 express的中间件bodyParser详解 flash+jQuery实现可关闭及重复播放的压顶广告 JS返回上一页实例代码通过图片和按钮分别实现 Linux怎么创建副本? Linux创建副本的教程 PHP正则删除html代码中a标签并保留标签内容的方法 原创 jQuery中$.grep() 过滤函数 数组过滤 基于jQuery实现点击弹出层实例代码 手机端网页点击链接触发自动拨打或保存电话的示例代码 jquery checkbox的相关操作总结 简单介绍CSS hack的使用 Node.js利用断言模块assert进行单元测试的方法 Thinkphp关闭缓存的方法 MySQL root密码忘记后更优雅的解决方法 ASP.NET4 GridView的四种排序样式详解 浅谈ASP.NET常用数据绑定控件优劣总结 JavaScript观察者模式(经典) python扫描proxy并获取可用代理ip的实例 vue-router 实现导航守卫(路由卫士)的实例代码 asp.net+ajax的Post请求实例 JAVA_JSP学习系列之八(改写MySQL翻页例子) 使用Mac帮助菜单快速查找菜单项教程 ASP.NET MVC中将控制器分离到类库的实现 JS实现的将html转为pdf功能【基于浏览器端插件jsPDF】 sql添加数据后返回受影响行数据 AngularJS的Filter的示例详解
easyui+springMVC+mybatis+sqlserver框架搭建模板 MSN频道四屏flash滑动门效果.zip 【ASP.NET源码】asp.net中拍大头帖的源码 v1.0_dtp.zip 微信小程序源码-微笑话 android电话拨打与发送短信实例demo jQuery相册滚动响应特效.zip CSS3鼠标悬停图片放大效果.zip 自适应医疗与健康HTML5模板 微信小程序源码-仿斗鱼直播小程序 jQuery键盘按钮响应事件代码.zip 【PHP源码】VBulletin 3.8.2_vbulletin.v3.8.2.zip 精美后台UI框架整站模板.zip 【ASP.NET源码】dxbbs大侠论坛 v8.1 MSSQL build 0311_dxbbs81-mssql.zip 简单的jquery放大镜特效.zip jQuery滑动拉伸导航按钮.zip SVG轻量级JS圆形进度条代码.zip 微信小程序 - 机器人兔兔.zip js画布裁剪插件.zip Discuz! x2大自然风格模板.zip 类似时间轴布局HTML5模板.zip PicassoDemo jquery右侧固定层QQ在线客服代码.zip JS九宫格布局随机闪烁特效.zip jQuery迷你帮助 查找功能.zip jQuery鼠标响应式灯光效果.zip 网站左侧下拉菜单jQuery代码.zip 【ASP.NET源码】乘风电影程序 v3.83 SQL_cffilmsql.zip jQuery带标题的3D图片切换代码.zip 描边按钮jQuery淡入淡出幻灯片.zip jQuery倒计时插件FlipTimer.zip 【ASP.NET源码】安源新闻系统 v4.2_aynews.zip jquery新浪微博表情插件.zip jQuery平面图区域标记拖拽移动代码.zip jQuery滑块拖动选择价格特效.zip 根据滚动自动调整导航栏大小.zip jq大图淡入淡出效果.zip HTML5大气单页商业网站模板.zip html5+css3齿轮滚动动画特效.zip 微信小程序源码-招聘 CSS3实现打钩高亮按钮.zip jQuery渐变图钉分层菜单.zip 带表情kindEditor编辑器.zip Canvas移动手机刮刮卡特效.zip 优雅大气帝国cms博客模板.zip jQuery横向手风琴图片滑块.zip 建筑公司网页模板下载.zip jplayer歌词同步音乐播放器.zip 基于j2ee书城项目 jQuery横向下拉导航菜单.zip 淡蓝色大屏幻灯片网站模板.zip 新闻博客CSS网页模板.zip jQuery带遮罩高亮图片滑动切换代码.zip 个人博客html模板下载.zip jQuery迅雷首页全屏图片切换代码.zip 【PHP源码】PJBLOG2 to Sablog-x 1.6 转换程序_pjblog2.zip jquery判断浏览器版本过低代码.zip 关于自己技能介绍网站模板.zip 网站后台管理静态页面及前台模板页面 Orbit仿新浪电影频道2013版幻灯片.zip jquery+css3动画幻灯片代码.zip spring+mybatis+spring-mvc+maven 项目框架 显微镜厂家官网网站模板.zip leomoon-cpu-v 检测电脑是否支持并开启虚拟化技术 bootstrap多级导航菜单代码.zip html5+css3下拉菜单.zip 微信小程序源码-教育一号 javaapplet+SQL 阳光酒店管理系统 jQuery自动填充表单功能代码.zip js+css圆形修边搜索框.zip jQuery焦点图片轮播插件Juicy Slider.zip jQ响应式多级菜单.zip 8种fakeloader页面加载动画效果.zip 2016入侵渗透免费视频课程 jquery滑动复选框菜单.zip jQuery带箭头动画弹出幻灯片.zip JAVA毕业设计项目-CRM客户关系管理系统 jquery模拟windows桌面.zip jquery实现图片翻牌旋转特效.zip jquery竖直倾斜导航.zip 自定制主机jQuery滑块.zip 微信小程序源码-简易抽奖 jQuery+CSS3提示框按钮过渡效果.zip CSS3实现3D纸片折叠动画.zip CSS3 3D立体分页插件.zip 【PHP源码】LOOKAN bt小偷v3.2_bt.zip jQuery开关按钮特效.zip jQuery+CSS3页面刷新加载效果.zip jquery凹陷导航效果.zip 旅游酒店官网网站模板.zip CSS3实现工厂流水线动画.zip jQuery带底部返回顶部按钮代码.zip html5触发式音频播放.zip springboot+dubbo+zk Struts2+Hibernate+Spring实现BBS论坛系统源码下载 SpringMVC3.0+Hibernate3.0+jQuery+Mysql实现登录注册(完整版) 基于SSM、shiro的企业权限管理系统 绿色商务办公网站模板.zip jQuery网站logo动态展示.zip jquery展开收缩手风琴菜单.zip 可任意翻转HTML5立方体.zip 吉他演奏html网站模板.zip jQuery爆炸效果炫酷轮播焦点图.zip jquery图片栅格替换效果.zip jquery快速排序算法动画特效.zip 黑色个性设计网站模板.zip Android 上下滑动引导页 扩展性强 支持各种布局 demo 免费下载 微信小程序源码-笑话集(含后端) 和谐家庭儿童网站模板.zip 好孩子满屏jQ焦点图.zip 黑暗主题CSS网页模板.zip 【PHP源码】php ajax 域名查询_domainsearch.zip jQuery多功能垂直幻灯片.zip css3分页导航.zip div+css银行提现手机表单代码.zip HTML5 3D小球弹跳动画.zip 【ASP.NET源码】伊新论坛免费修改版 vv0.1_knetbbsv205build821.zip CSS3实现颜色渐变菜单.zip jQuery+CSS3点击动画弹出表单代码.zip 适合甜品店的CSS3幻灯片特效.zip jQuery+CSS3弹性过渡全屏翻页特效.zip Android xutils的数据库增删改查带数据库升级 微信小程序源码-车源宝寻车广场 H5上传图片文件 平面设计全屏官网企业模板.zip jQuery播放器在线音乐电台代码.zip jQuery自动滚动五屏图片通栏代码.zip jQuery星星评分插件.zip 公路背景倒计时网站模板.zip jQuery图标导航插件imgbubbles.zip 地理知识html模板下载.zip jquery带对话框提示图片相册.zip Android蓝牙聊天项目 java百度地图瓦片批量下载demo jQuery隐藏显示密码插件.zip jQuery touchSlider满屏焦点图.zip 鼠标悬停文字旋转动画导航代码.zip JSP+SERVLET+MYSQL实现的权限管理,学生宿舍管理系统 橙色装修公司html5模板.zip jQuery仿A站视频弹幕代码.zip 观天下足球直播网站模板.zip 【ASP.NET源码】长登企业建站系统 v1.3 bulid 090328_ppfor.zip jQuery文字无缝滚动效果代码.zip 红色的爱玛客小礼品购物商城网站模板html源码.zip 水果拼盘美食网站模板.zip 手机APP应用设计网站模板.zip 微信小程序源码-美容美甲商城 jquery+css3飞机窗口动画特效.zip 太阳能发电企业网站模板.zip 暗月提权VIP系列培训视频 领智网站内容管理系统 v2.02 黄色风格音乐网页模板.zip 【ASP.NET源码】NBear+NBear开发BBS系统源码_nbearbbs.zip 【Android】可拖拽排序的ListView 自定义视频录制,保存20秒录制内容 Android万能播放器 Spring3mvc和hibernate整合示例代码 性感模特拍摄公司网站模板.zip jQuery旋钮插件jQuery knob.zip jQuery flexslider焦点图.zip 商业设计css+div模板下载.zip 【PHP源码】渝海Alexa排名查询工具 v1.4_yh_alexa.zip 博客设计css模板下载.zip 微信小程序源码-图书管理系统 QQ空间wordpress主题.zip WP移动设备Bing-Phone主题.zip Struts2+Hiberntate+Spring档案管理系统,数据库和包完整 微信小程序源码-美容商城 css3文字模糊渐变效果.zip 图片集鼠标悬停CSS3过渡效果.zip 新浪flash图片轮播广告.zip SVG+CSS3实现弹性跳动动画特效.zip js制作经典俄罗斯方块游戏代码.zip jQuery天猫商城banner焦点图.zip 微信小程序 - 足球圈(包含node后端).zip Web版的超市管理系统后台网页模板 jQuery流媒体音乐播放器特效.zip jQuery数字滚动播放动画特效.zip 蓝色滑动视差单页网站模板.zip 带语音录入的搜索框特效.zip prettyPhoto图片滚动展示.zip 带放大效果jquery左右滚动图片代码.zip Java调用Redis 简单Demo jQuery汽车车速表效果.zip jquery弹性幻灯片.zip 2014本来生活网ecshop模板.zip 旅游酒店在线预订网站模板.zip js滚动产品图片代码.zip html5 canvas圣诞雪花网页背景代码.zip 【PHP源码】phorum 5.2.13 for Linux_codepub-phorum.zip 葡萄酒进口公司网站模板.zip 地方分类信息帝国模板.zip Bootstrap水晶玻璃按钮特效.zip 【HTML5响应式系列之小情绪风格】仿Epsilon Elements触屏版html5响应式手机wap网站模板下载.zip ECShop 仿麦包包模板.zip 微信小程序源码-轮播图+菜单 jQuery跨浏览器控制图标旋转代码.zip 微信小程序源码-物业管理 纯CSS3实现眨眼动画特效.zip CSS3鼠标悬停图片文字动画效果代码.zip CSS3登录注册表单滑动切换特效.zip
举报X