扩展KMP算法
一 问题定义
给定母串S和子串T,定义n为母串S的长度,m为子串T的长度,suffix[i]为第i个字符开始的母串S的后缀子串,extend[i]为suffix[i]与字串T的最长公共前缀长度。求出所有的extend[1..n]。容易发现,如果存在某个i,使得extend[i] = m,这便是经典的KMP算法要解决的问题。
二 扩展KMP算法思想
和KMP算法的是想类似,充分利用已经比较字符性质来减少冗余的字符比较次数。KMP的思想是充分的利用模式串中所有前缀字串(以模式串为开头的字串)的真前缀和真后缀(指子串的开始字符与子串的最后字符相等的个数)来减少不必要的字符比较,真前缀和真后缀相等的个数保存在next数组中。扩展KMP算法则是利用子串T中的所有后缀子串suffix[i]与字串T的最长公共前缀来减少字符的比较次数,这个最长公共前缀的个数也记录在next数组中。
假设我们已经求出了extend[0..k]并且记录了a和p,p表示在S串中从第i(i=0..k)个字符开始匹配的过程中达到的最远的位置,a表示取p这个最大值所对应的i值。现在求extend[k+1],可以分下面三种情况:
- k+1==p(p肯定是大于或等于k+1的)
直接S[k+1]与T[0]开始比较,并更新a和p的值 - k + 1 + next[k - a + 1] <= p
extend[k+1] = next[k - a + 1] - k + 1 + next[k - a + 1] > p
直接S[p]与T[p - k -1]开始比较,extend[k+1]也对应的从p - k - 1开始往后加,并更新a和p的值
对于第二种和第三种情况怎么得到的呢?这就要靠我们保存的a和p了。如果p > k + 1,那么必然有S[k+1,p-1] = T[k-a+1,p-a],这个可以通过S[a,p-1] = T[0,p-a]推出。我们在next[k-a+1]中保存了T的suffix[k-a+1]子串与T的最长公共前缀的长度,假设L=next[k-a+1],那么T[k-a+1,k-a+L]=T[0,L-1]。如果k+1+L<= p,通过S[k+1,p-1] = T[k-a+1,p-a],可以得到S[k+1,k+L]=T[k-a+1,k-a+L]=T[0,L-1],并且S[k+L+1]!=T[0,L]的(因为如果相等的话,T[k-a+1,k-a+L+1]=T[0,L],这与前面的T[k-a+1,k-a+L]=T[0,L-1]是矛盾的),所以extend[k+1]=L。如果k+1+L> p,那么S[k+1,p-1] = T[k-a+1,p-a]=T[0,p-k-2],所以extend[k+1]至少等于p-k-1,然后我们应该继续从p开始比较,因为从p开始都是没有比较过的。
求next的思路和求extend的思路是一样的,只不过是T对自己求extend。
三 扩展KMP算法实现
#define MAXSIZE 400005
int extend[MAXSIZE], next[MAXSIZE]; void get_next(char *t, int n)
{
int a, p, k, i; next[] = ;
a = ;
p = ;
for (k = ; k < n; k++)
{
if (k == p)
{
i = k;
while (t[i] == t[i - k])
i++;
next[k] = i - k;
if (i == p)
p++;
else
p = i;
a = k;
}
else if (k + next[k - a] <= p)
next[k] = next[k - a];
else
{
next[k] = p - k;
i = p;
while (t[i] == t[i - k])
{
i++;
next[k]++;
}
if (i > p)
{
p = i;
a = k;
}
}
}
} void get_extend(char *s, int sn, char *t, int tn)
{
int a, p, k, i; p = a = ;
for (k = ; k < sn; k++)
{
if (k == p)
{
i = k;
while (i - k < tn && s[i] == t[i - k])
i++;
extend[k] = i - k;
if (i == p)
p++;
else
p = i;
a = k;
}
else if (k + next[k - a] <= p)
extend[k] = next[k - a];
else
{
extend[k] = p - k;
i = p;
while (i - k < tn && s[i] == t[i - k])
{
i++;
extend[k]++;
}
if (i > p)
{
p = i;
a = k;
}
}
}
}
扩展KMP算法的更多相关文章
- 扩展KMP算法小记
参考来自<拓展kmp算法总结>:http://blog.csdn.net/dyx404514/article/details/41831947 扩展KMP解决的问题: 定义母串S和子串T, ...
- 神奇的字符串匹配:扩展KMP算法
引言 一个算是冷门的算法(在竞赛上),不过其算法思想值得深究. 前置知识 kmp的算法思想,具体可以参考 → Click here trie树(字典树). 正文 问题定义:给定两个字符串 S 和 T( ...
- 扩展KMP——算法总结,来自于 迷路的鸽子
扩展kmp LRH 所谓扩展kmp指的是与kmp相似的求辅助数组的原理,但是本身与kmp关系不大. 1.exkmp的用途:给定一个主串s和一个子串t,求出s中每一个后缀 ...
- (模板)扩展kmp算法(luoguP5410)
题目链接:https://www.luogu.org/problem/P5410 题意:有两个字符串a,b,要求输出b与a的每一个后缀的最长公共前缀.输出: 第一行有lenb个数,为b的next数组( ...
- 浅谈Manacher算法与扩展KMP之间的联系
首先,在谈到Manacher算法之前,我们先来看一个小问题:给定一个字符串S,求该字符串的最长回文子串的长度.对于该问题的求解.网上解法颇多.时间复杂度也不尽同样,这里列述几种常见的解法. 解法一 ...
- KMP算法模板&&扩展
很不错的学习链接:https://blog.csdn.net/v_july_v/article/details/7041827 具体思路就看上面的链接就行了,这里只放几个常用的模板 问题描述: 给出字 ...
- HDU3613 Best Reward —— Manacher算法 / 扩展KMP + 枚举
题目链接:https://vjudge.net/problem/HDU-3613 Best Reward Time Limit: 2000/1000 MS (Java/Others) Memor ...
- 初探KMP算法
数据结构上老师也没讲这个,平常ACM比赛时我也没怎么理解,只是背会了代码--前天在博客园上看见了一篇介绍KMP的,不经意间就勾起了我的回忆,写下来吧,记得更牢. 一.理论准备 ...
- 扩展KMP --- HDU 3613 Best Reward
Best Reward Problem's Link: http://acm.hdu.edu.cn/showproblem.php?pid=3613 Mean: 给你一个字符串,每个字符都有一个权 ...
随机推荐
- linux(centos)下挂载ntfs文件系统
在将硬盘插到Linux系统上,打开硬盘时一直提示:unknown filesystem type 'ntfs'.在尝试网上的方法也遇到了一些问题. 下面按照遇到的问题,按照正确的方式注意操作从而避免问 ...
- [LintCode] Sort List 链表排序
Sort a linked list in O(n log n) time using constant space complexity. Have you met this question in ...
- *POJ1830 高斯消元
开关问题 Time Limit: 1000MS Memory Limit: 30000K Total Submissions: 8010 Accepted: 3161 Description ...
- HTML5新标签<canvas>
基本用法 首先在body中写个<canvas>,设定大小,个人建议大小要在行内设置,不然在部分情况下会发生错误. CSS部分 给canvas加个边框,这边框只是为了方便看出canvas的边 ...
- .保护Express应用程序
毫无疑问,Node.js已经变的愈加成熟,尽管这样,开发者仍然缺乏大量的安全指南.在这篇文章中,我将分享一些有关Node.js安全要点给大家,希望大家能够谨记于心. 1.避免使用Eval Eval并不 ...
- Android WiFi密码(查看工具)
纯手机端AIDE编写,现在分享出源码 & apk文件. 注: 使用此工具需要root权限. apk文件 : http://yunpan.cn/cHPLZ8zH5BQBV (提取码:9cd2) ...
- 关于MongoDB你需要知道的几件事
Henrique Lobo Weissmann是一位来自于巴西的软件开发者,他是itexto公司的联合创始人,这是一家咨询公司.近日,Henrique在博客上撰文谈到了关于MongoDB的一些内容,其 ...
- HappyAA服务器部署笔记2(nginx的静态资源缓存配置)
我近期对服务器进行了少量改进,虽然之前使用了nginx反向代理之后性能有所提高,但仍然不够,需要使用缓存来大幅度提高静态资源的访问速度. 服务器上的静态资源主要有这些:png, jpg, svg, j ...
- 女生的最爱,装饰品。WPF也有,Adorner。(上海晒衣服理念)
说到装饰,不由要说到女性. 去年过年回家给我妈买了周大福项链,很明显就感觉待遇就不一样了,即使这样,还是被一个阿姨说应该买更重点的.看来钱这种东西果然是多一点才好.虽然自己无所谓,但让家里人更开心也是 ...
- 有点担心Node.js的未来了
原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com 首先本文的目的不是引发语言之争,纯属个人的一些思绪记录. 因为工作原因,用Node.js做过几个项目,基本都是涉及 ...