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 平分算法吗?理论上和通过代码片段[重复]