扩展KMP (EX-KMP)
next数组和extend数组
设有字符串S,T,next[i]表示T[i...len]与T[0..len]的最长公共前缀,extend[i]表示S[i...len]与T[0...len]的最长公共前缀,扩展kmp要做的就是把extend数组求出来.
思路
假设当前在匹配到s串的i位置,设p=i,然后开始比较while(S[p]==T[p-i]) p++,此条件一直满足直到p=p0时不成立,也就是说S[i....p-1]=T[0....p-1-i],此时记extend[i]=p-i,a=i.那么接下来i从i+1到p的过程中,只有以下三种情况:
(1)i+next[i-a]<p;
此时由于S[a...p-1]=T[0...p-1-a],有S[i...p-1]=T[i-a...p-a],而i+next[i-a]也不超出p-1等价于i-a+next[i-a]不超出p-1-a,所以有extend[i]=next[i-a].
(2)i+next[i-a]>=p;
此时i+next[i-a]已经超出p-1,而我们从a出发只能确定S[a...p-1]的字符信息,因此要以此时的i为起点重新开始最初的匹配过程,因为有S[i..p-1]=T[i-a..p-a],且i+next[i-a]>=p等价于i-a+next[i-a]>=p-a,也就是说从S[i...p-1]=T[0...p-1-a],因此不需要重新从i开始对比,只需要继续从上次的p开始对比S[p]==T[p-i]下去就行了,直接执行while(S[p]==T[p-i]) p++,更新操作和之前一样.
(3)i>=p;
如上所说我们只能确认S[a...p-1]的字符信息,因此在p字符之后只能重新开始比对--设p=i,然后开始执行while(S[p]==T[p-i]) p++,更新操作和之前一样.
以上方法可以同求next数组和extend数组,在求next数组时只需把上述s串也当成t串就行了.
代码
1 string s,t; 2 int next[MAX]; 3 int extend[MAX]; 4 5 void get_next(int n) 6 { 7 next[0]=n; 8 int a=0,p=0; 9 for(int i=1;i<n;i++) 10 { 11 if(i+next[i-a]>=p) 12 { 13 if(i>=p) p=i; 14 while(p<n&&t[p]==t[p-i]) p++; 15 next[i]=p-i; 16 a=i; 17 } 18 else next[i]=next[i-a]; 19 } 20 } 21 22 void exkmp(int n,int m) //n为s串长度,m为t串长度 23 { 24 get_next(m); 25 int a=0,p=0; 26 for(int i=0;i<n;i++) 27 { 28 if(i+next[i-a]>=p) 29 { 30 if(i>=p) p=i; 31 while(p<n&&p-i<m&&s[p]==t[p-i]) p++; 32 extend[i]=p-i; 33 a=i; 34 } 35 else extend[i]=next[i-a]; 36 } 37 }
原文地址:https://www.cnblogs.com/VBEL/p/11308549.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- IOC XMLBeanDefinitionReader
- 利用lynis如何进行linux漏洞扫描详解
- Linux shell命令用法及常见用例之tar命令
- Linux 下解压 rar 文件的方法
- Redis数据结构-压缩列表
- HTTP文件缓存判断流程
- Linux系统 为命令配置别名的方法
- Redis数据结构-跳跃表
- Canvas系列(10):动画初级
- Canvas系列(5):绘制文字
- 详解Keepalived安装与配置
- Redis数据结构-字典
- 编程体系结构(07):JavaEE之Web开发
- Centos 6.5环境实现本地局域网搭建YUM的方法【基于HTTP】
- Doug Lea在J.U.C包里面写的BUG又被网友发现了。