这个算法太狗血,弄了好几天才明白一点,而且网上不同的博客写的方法不相同,表示很无奈啊。。。
接下来我要讲一讲我理解的KMP,我理解的有点浅,主要给几个事例,就不模拟计算过程了,具体KMP是什么,或者想要知道大致模拟过程的,自行百度。
求字符串在另一个字符串重复了几次
先粘上代码
#include <bits/stdc++.h> using namespace std; typedef long long LL; int next[10000]; void prekmp(char x[], int m) {//这一步坑爹,next数组为一张部分匹配表 int i = 0, j = -1; next[0] = -1; while(i < m) { while(j != -1 && x[i] != x[j] ) j = next[j]; if(x[++i] == x[++j]) next[i] = next[j]; else next[i] = j; } } int KMP(char x[], int m, char y[], int n) {这个还好理解 int i = 0, j = 0; int ans = 0; prekmp(x, m); while(i < n) { while(j != -1 && x[j] != y[i]) j = next[j];//用到next数组,不用一个一个对比,直接用放在next的位置,位置文章最后有解释 i++; j++; if(j >= m) { ans++; j = next[j]; } } return ans; } int main() { //freopen("in.txt","r",stdin); //freopen("out.txt,"w",stdout"); ios_base::sync_with_stdio(0);cin.tie(); char x[10000], y[10000]; scanf("%s%s",y,x); int m = strlen(x); int n = strlen(y); cout << endl; cout << KMP(x, m, y, n) << endl; for(int i = 0; i < m; i++)//print value cout << next[i] << "" ; cout << endl; return 0; }
next数组的事例
位置都是从0开始
abc -1 0 0
abca -1 0 0 -1 如果字母跟首字母相同,就为-1
abcabe -1 0 0 -1 0 2 e字母和c字母不相同,所以e字母指向c的位置
abcdabead -1 0 0 0 -1 0 2 -1 1 第三个a同第三个a之前字符串的比较,最后一个字母d指向第二个字母b的位置
abcabcabde -1 0 0 -1 0 0 -1 0 5 0 第三个a之前有连续重复的,第三个指向第6个字母的位置
abcabdabea -1 0 0 -1 0 2 -1 0 2 -1 第三个a之前的不连续,所以指向第三个字母的位置