KMS算法

Posted Carlos

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了KMS算法相关的知识,希望对你有一定的参考价值。

解题:http://hihocoder.com/problemset/problem/1015

KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt同时发现,因此人们称它为克努特——莫里斯——普拉特操作(简称KMP算法)。KMP算法的关键是利用匹配失败后的信息,尽量减少模式串与主串的匹配次数以达到快速匹配的目的。具体实现就是实现一个next()函数,函数本身包含了模式串的局部匹配信息。时间复杂度O(m+n)。

概念问题

主串S:就是比较长的那个字符串

模式串P:比较短的字符串

算法的功能:从比较长的字符串里面去找到比较短的字符串。

算法核心:

主串S: BBC ABCDAB ABCDABCDABDE

模式串P: ABCDABD

1)分析模式串

 

2)当匹配到不同的字符的时候去根据next数组去查找最多的移动距离  最多的移动距离是把P的起始位置移动到当期位置移动到上一个匹配数为0的元素。   :移动位数 = 已匹配的字符数 - 对应的部分匹配值

 c++ Accept代码:

#include <iostream>
#include <vector>

using namespace std;

/**
* @function 求得模式串的next数组
* @param p 模式串
* @param next next数组
*/
void getNext(const string p, vector<int> &next) {
next[0] = -1;
int lenP = p.size();
int j = 0;
for (int i = 1; i < lenP; i++) {
if (p[i] == p[j]) {
j++;
next[i] = j - 1;
} else {
next[i] = j;
j = 0;
}
}
}

/**
* @function 求kms算法找到的完全匹配的次数
* @param s 主串
* @param p 模式串
* @param next 模式串的next数组
* @return 匹配到的个数
*/
int kmp(const string s, const string p, const vector<int> next) {
int ans = 0, lenS = s.size(), lenP = p.size(), i = 0, j = 0;
while (i < lenS) {
if (j == -1 || s[i] == p[j]) {
i++;
j++;
if (j == lenP) {
ans++;
j--;
i--;
j = next[j];
}
} else {
j = next[j];
}

}
return ans;

}

int main() {


int loopTime = 0;
cin >> loopTime;
for (int i = 0; i < loopTime; i++) {
string s, p;
cin >> p >> s;
vector<int> next(p.size());
getNext(p, next);
cout << kmp(s, p, next) << endl;
}
return 0;
}

  

以上是关于KMS算法的主要内容,如果未能解决你的问题,请参考以下文章

以下代码片段的算法复杂度

有人可以解释啥是 SVN 平分算法吗?理论上和通过代码片段[重复]

片段(Java) | 机试题+算法思路+考点+代码解析 2023

CentOS7 一键安装KMS服务整理

使用 KMS 时尝试将某些代码转换为 Go CDK

KMS 加密 - 本地开发