【算法】字符串匹配之Z算法
求文本与单模式串匹配,通常会使用KMP算法。后来接触到了Z算法,感觉Z算法也相当精妙。在以前的博文中也有过用Z算法来解决字符串匹配的题目。
下面介绍一下Z算法。
先一句话讲清楚Z算法能求什么东西。
输入为一个字符串s,Z算法可以求出这个字符串每一个后缀与自身的最长公共前缀LCP,Z算法可以求出一个数组z,z[i]表示suffix(i)与字符串本身的最长公共前缀。
接下来,介绍Z算法的具体内容。
记字符串s的长度为n。
Z算法需要维护一对值,记为left和right,简记为L和R。L和R满足s[L,R]为s串的前缀。当i为1的时候,暴力比较s[0,n-1]与s[1,n-1]可得此时的L与R,同时也得到了z[1],即suffix(1)与s本身的LCP。
假设计算至i-1,我们已经得到了当前的L与R,同时也得到了z[1]到z[i-1]的值,现在需要计算z[i]与新的L和R。
1.假设i>R,则说明不存在一个结束于i或者i之后的串,同时这个串本身也为s的一个前缀,否则R不应该小于i。对于这种情况,需要重新计算新的L与R,令L=R=i,暴力比较s与suffix(i),得到z[i]=R-i+1=R-L+1。
2.此时i<=R,令k=i-L,可以断言z[i]>=min(z[k],R-i+1)。因为根据L与R的含义,此时我们可以将L到R视作为字符串的前缀,那么i相对于L的偏移量为k。
如果z[k]<R-i+1,则z[i]必然等于z[k],基于此时,s[k,k+z[k]-1]是s[i,R]的一个前缀,同时在这种情况下L与R不变。
如果z[k]>=R-i+1,根据R的含义可知s[R+1]!=s[R-L+1],z[k]中大于R-i+1的匹配信息因为s[R+1]!=s[R-L+1]而无效,但这并不意味着s[R+1]!=s[R-i+1],此时根据z[k]可以断言z[i]至少是R-i+1,是否可以更大需要再进行计算,令L=i,更新R值,并得到此时的z[i]。
具体实现中,第二种情况的两种子情况可以归一化处理。
给出一个C++实现代码:
void Z(char *s,int n=) {
n=(n==)?strlen(s):n;
z[]=n;
int l=,r=;
for (int i=;i<n;i++) {
if (i>r) {
l=i,r=i;
while (r<n&&s[r-i]==s[r]) r++;
z[i]=r-l;
r--;
}
else {
int k=i-l;
if (z[k]<r-i+)
z[i]=z[k];
else {
l=i;
while (r<n&&s[r-i]==s[r]) r++;
z[i]=r-l;
r--;
}
}
}
}
过程中每个字符至多被L和R扫到一次,Z算法是线性的复杂度。
Z算法解决单模式串匹配的方法很简单,令S为文本串,T为模式串,构造新串P=T+'#'+S,计算z数组,从S在P中开始的位置向后扫描,如果z[i]=length(S),则说明此处有一个匹配。当然其实也可以不加'#',那样子的话判断需要用>=而不是=。相较于KMP,对于解决单模式串匹配,如求所有匹配位置,其实用Z算法求的话是可以做到不用额外空间的(对于字符串拼接,可以不用开一个新的字符串。过程中判断匹配即可,不必保存z数组。),而KMP的话,不保存模式串的next数组,是没办法进行匹配运算的。
【算法】字符串匹配之Z算法的更多相关文章
- 算法——字符串匹配之BM算法
前言 Boyer-Moore算法是一种基于后缀匹配的模式串匹配算法(简称BM算法),后缀匹配就是模式串从右到左開始比較,但模式串的移动依旧是从左到右的.在实践中.BM算法效率高于前面介绍的<KM ...
- 实现字符串匹配的KMP算法
KMP算法是Knuth-Morris-Pratt算法的简称,它主要用于解决在一个长字符串S中匹配一个较短字符串s. 首先我们从整体来把我这个算法的思想. 字符串匹配的朴素算法: 我们容易想到朴素算法, ...
- Luogu 3375 【模板】KMP字符串匹配(KMP算法)
Luogu 3375 [模板]KMP字符串匹配(KMP算法) Description 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来 ...
- 字符串匹配的 Boyer-Moore 算法
上一篇文章,我介绍了 字符串匹配的KMP算法 但是,它并不是效率最高的算法,实际采用并不多.各种文本编辑器的” 查找” 功能(Ctrl+F),大多采用 Boyer-Moore 算法. 下面,我根据 M ...
- 字符串匹配的 KMP算法
一般字符串匹配过程 KMP算法是字符串匹配算法的一种改进版,一般的字符串匹配算法是:从主串(目标字符串)和模式串(待匹配字符串)的第一个字符开始比较,如果相等则继续匹配下一个字符, 如果不相等则从主串 ...
- 字符串匹配的kmp算法 及 python实现
一:背景 给定一个主串(以 S 代替)和模式串(以 P 代替),要求找出 P 在 S 中出现的位置,此即串的模式匹配问题. Knuth-Morris-Pratt 算法(简称 KMP)是解决这一问题的常 ...
- HDU 1711 Number Sequence (字符串匹配,KMP算法)
HDU 1711 Number Sequence (字符串匹配,KMP算法) Description Given two sequences of numbers : a1, a2, ...... , ...
- 字符串匹配(KMP 算法 含代码)
主要是针对字符串的匹配算法进行解说 有关字符串的基本知识 传统的串匹配法 模式匹配的一种改进算法KMP算法 网上一比較易懂的解说 小样例 1计算next 2计算nextval 代码 有关字符串的基本知 ...
- 字符串匹配的KMP算法
~~~摘录 来源:阮一峰~~~ 字符串匹配是计算机的基本任务之一. 举例来说,有一个字符串”BBC ABCDAB ABCDABCDABDE”,我想知道,里面是否包含另一个字符串”ABCDABD”? 许 ...
随机推荐
- Dollar Dayz poj3181
http://poj.org/problem?id=3181 这个题目一开始就能看出来是个dp问题,但是我并没有一开始就看出来是一个完全背包为题,只是想着根据以前的方法,这个问题应该是可以找到规律的, ...
- PHP数据访问易错点(20161030)
易错点: 1.造对象的时候括号里面的参数 写错了 $db = new MySQLi("localhost","root","789",&qu ...
- web从入门开始(5)-----表单
1. 表单的概念 是用来获取客户端用户数据的(信息)的.如:注册表单,查询表单,登录表单等. 2. 表单的工作原理 1.浏览有表单的网页,填写一些必要的信息,然后单击某个按钮,进行提交. 2.这 ...
- 简学Python第六章__class面向对象编程与异常处理
Python第六章__class面向对象编程与异常处理 欢迎加入Linux_Python学习群 群号:478616847 目录: 面向对象的程序设计 类和对象 封装 继承与派生 多态与多态性 特性p ...
- 知问前端——html+jq+jq_ui+ajax
**************************************************************************************************** ...
- JD . 圆角矩形、权重层级、浮动撑开盒子及元素的默认间距、清除浮动、隐藏盒子、盒子的撑开与撑破、子盒子垂直居中|不占位置
---恢复内容开始--- 圆角矩形 border-radius:50% 40% 30% 33px: 像素.百分比.小数( 0.5 ) 左上.右上.右下.左下 权重: 标签 1 : 类选择器 ...
- node.js下mongoose简单操作实例
Mongoose API : http://mongoosejs.com/docs/api.html // mongoose 链接var mongoose = require('mongoose'); ...
- 彻底理解容器类(2)------- AbstractCollection深入了解
h2 { background-color: Skyblue } AbstractCollection认识 AbstractCollection是Collection接口的抽象实现.实现了一部分Col ...
- VM安装centos
1,centOS下载地址:http://mirrors.163.com/centos/7/isos/x86_64/ 2,VM下载地址:http://rj.baidu.com/soft/detail/1 ...
- Java日期格式化方法
首先获取当前系统时间的方法有两种:第一种可以用currentTimeMillis()方法获取,它其实产生的是一个当前的毫秒数,这个毫秒是自1970年1月1日0时起至现在的毫秒数,类型是long 型,可 ...