kmp字符串匹配
看了一个晚上才搞懂,果然是太蒟蒻了。
kmp匹配主要是用于在一个字符串中查找一个比它小的字符串的位置,在传统的暴力算法中,时间复杂度会达到m*n,所以这时候就出现了更加快的kmp匹配算法。
和其他更快的算法相同,kmp也是一种用空间换时间的算法,通过对要查找的字符串的预处理来达到更快的效果,实际时间复杂度可以达到m+n。
讲了那么多我们应该如何来实现kmp算法呢。
首先我们得理解一个前缀子串和后缀字串的概念。
打个比方有个字符串abab
那么它的前缀子串便有 a,ab , aba
它的后缀子串 bab,ab ,b
这时他们最长的相同前缀后缀子串便是ab
我们要用kmp算法最重要的是一个next[i]数组,里面储存的就是要匹配的字符串前i项的最长相同子串大小。
比如还是上面那个字符串 next[1]=0,next[2]=0,next[3]=1,next[4]=2
那这个数组有什么用呢;
比方说我们有一个字符串abacab,要在其中查找abab
这时我们匹配到c发现与要查找的不同,但是它的前3项是相同的,由kmp数组我们可以知道next[3]=1
所以abab的前一项和abacab的前三向的最后一项是相同的,我们就可以直接把abab的第一项移到abacab的前三向的最后一项进行匹配这样就可以快很多。
#include<iostream> #include<stdio.h> #include<cstring> using namespace std; char a[1000000], b[10000000]; int kmp[10000000]; int main() { cin >> a+1 >> b+1; int len1 = strlen(a + 1), len2 = strlen(b + 1); int j = 0; for (int i = 2; i <= len2; i++) { while (j && b[i] != b[j+1])j = kmp[j]; if (b[j + 1] == b[i])j++; kmp[i] = j; } j = 0; for (int i = 1; i <= len1; i++) { while (j && a[i] != b[j + 1])j = kmp[j]; if (b[j + 1] == a[i])j++; if (j == len2) { cout << i - len2 + 1 << endl; j = kmp[j]; } } for (int i = 1; i <= len2; i++) cout << kmp[i] << " "; return 0; }

浙公网安备 33010602011771号