算法提高 第一期 KMP扩展算法

1## 具体思路:

和KMP算法的是想类似,充分利用已经比较字符性质来减少冗余的字符比较次数。KMP的思想是充分的利用模式串中所有前缀字串(以模式串为开头的字串)的真前缀和真后缀(指子串的开始字符与子串的最后字符相等的个数)来减少不必要的字符比较,真前缀和真后缀相等的个数保存在next数组中。扩展KMP算法则是利用子串T中的所有后缀子串suffixi与字串T的最长公共前缀来减少字符的比较次数,这个最长公共前缀的个数也记录在next数组中。

假设我们已经求出了extend0...k并且记录了a和p,p表示在S串中从第i(i=0...k)个字符开始匹配的过程中达到的最远的位置,a表示取p这个最大值所对应的i值。现在求extendk+1,可以分下面三种情况:

k+1==p(p肯定是大于或等于k+1的)

 直接Sk+1与T0开始比较,并更新a和p的值

k + 1 + nextk - a + 1 <= p

 extendk+1 = nextk - a + 1

k + 1 + nextk - a + 1 > p

直接Sp与Tp - k -1开始比较,extendk+1也对应的从p - k - 1开始往后加,并更新a和p的值

  对于第二种和第三种情况怎么得到的呢?这就要靠我们保存的a和p了。如果p > k + 1,那么必然有Sk+1,p-1 = Tk-a+1,p-a,这个可以通过Sa,p-1 = T0,p-a推出。我们在nextk-a+1中保存了T的suffixk-a+1子串与T的最长公共前缀的长度,假设L=nextk-a+1,那么Tk-a+1,k-a+L=T0,L-1。如果k+1+L<= p,通过Sk+1,p-1 = Tk-a+1,p-a,可以得到Sk+1,k+L=Tk-a+1,k-a+L=T0,L-1,并且Sk+L+1!=T0,L的(因为如果相等的话,Tk-a+1,k-a+L+1=T0,L,这与前面的Tk-a+1,k-a+L=T0,L-1是矛盾的),所以extendk+1=L。如果k+1+L> p,那么Sk+1,p-1 = Tk-a+1,p-a=T0,p-k-2,所以extendk+1至少等于p-k-1,然后我们应该继续从p开始比较,因为从p开始都是没有比较过的。

求next的思路和求extend的思路是一样的,只不过是T对自己求extend。

模板:

cpp 复制代码
for(int i = 2; i <= m + n; i ++)
	{
		if(i <= r) z[i] = min(z[i - l + 1], r - i + 1);
		while(s[1 + z[i]] == s[i + z[i]]) z[i] ++;
		if(i + z[i] - 1 > r) l = i, r = i + z[i] - 1; 
	}

例题:

AC代码:

cpp 复制代码
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int>PII;
const int N=3e5+10;
const int MOD = 1e9 + 7;
const int INF=0X3F3F3F3F;
const int dx[]={-1,1,0,0,-1,-1,+1,+1};
const int dy[]={0,0,-1,1,-1,+1,-1,+1};
const int M = 1e6 + 10;

int z[1001000];
int n, m;

int main()
{
	cin >> n;
	string a, b;
	cin >> a;
	cin >> m;
	cin >> b;
	string s = ' ' + a + b;
	int l = 1, r = 0;
	z[1] = n + m;//n小m大
	for(int i = 2; i <= m + n; i ++)
	{
		if(i <= r) z[i] = min(z[i - l + 1], r - i + 1);
		while(s[1 + z[i]] == s[i + z[i]]) z[i] ++;
		if(i + z[i] - 1 > r) l = i, r = i + z[i] - 1; 
	}
	for(int i = n + 1; i <= m + n; i ++)
	{
		if(z[i] == n) cout << i - n - 1 << " ";
	}
	return 0;
}
相关推荐
小欣加油1 分钟前
leetcode287寻找重复数
数据结构·c++·算法·leetcode
尽兴-31 分钟前
2.1 向量基础:Embedding、余弦相似度、欧氏距离、向量检索
算法·embedding·欧氏距离·向量检索·余弦相似度
Black蜡笔小新1 小时前
自动化AI算法训练服务器DLTM训推一体工作站赋能多行业智能化升级
人工智能·算法·自动化
怪兽学LLM1 小时前
LeetCode 438 找到字符串中所有字母异位词(Python 固定滑动窗口+字符计数解法)
python·算法·leetcode
满怀冰雪1 小时前
第04篇-双指针算法-从有序数组到回文判断的高频解法
java·算法
CC数学建模1 小时前
2026年江西省研究生数学建模竞赛1题:空间数据分析中的过拟合识别完整思路、代码、模型、文章,全网首发高质量分享!
python·算法·数学建模
leo__5201 小时前
MATLAB实现牧羊人算法
开发语言·算法·matlab
Gauss松鼠会2 小时前
【GaussDB】GaussDB SMP特性调优详解
java·服务器·前端·数据库·sql·算法·gaussdb
Tisfy2 小时前
LeetCode 3689.最大子数组总值 I:What The Medium
算法·leetcode·题解·贪心·模拟·脑筋急转弯
葬送的代码人生2 小时前
JavaScript 数组完全指南:从入门到实战
前端·javascript·算法