一、概述
烤馍片算法
主要应用场景为模式串(子串)在字符串(主串)中的定位问题,时间复杂度为O(n+m)
可用于计算最长相同前后缀长度,找寻主串中是否存在子串
二、实现
1.计算最长相同前后缀
kmp数组即next数组,字符串需从i=2开始,最前端需补一个空格,字符串长度需-1(因为前面多加了一个空格),即字符串的长度n
kmp[ lenb ]即为字符串中最长的相同前后缀
string b;
cin >> b;
b = " " + b;
int lenb = b.length() - 1;
for (int i = 2, j = 0; i <= lenb; kmp[i] = j, i++) {
while (j && b[i] != b[j + 1]) j = kmp[j]; //回滚
if (b[i] == b[j + 1]) j++;
}
2.是否存在子串
#include<bits/stdc++.h>
using namespace std;
#define qio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
const int N = 1e5 + 10;
int kmp[N];
int main() {
qio
string a, b;
cin >> a >> b;
a = " " + a, b = " " + b;
int lena = a.length() - 1, lenb = b.length() - 1;
for (int i = 2, j = 0; i <= lenb; kmp[i] = j, i++) {
while (j && b[i] != b[j + 1]) j = kmp[j];
if (b[i] == b[j + 1]) j++;
}
for (int i = 1, j = 0; i <= lena; i++) {
while (j && a[i] != b[j + 1]) j = kmp[j];
if (a[i] == b[j + 1]) j++;
if (j == lenb) {
cout << "Yes" << '\n';
return 0;
}
}
cout << "No" << '\n';
}
三、应用
1.Div.3 A. Many Equal Substrings
#include<bits/stdc++.h>
using namespace std;
#define qio ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
const int N = 4e3 + 10;
int kmp[N];
int main() {
qio
int n, k;
cin >> n >> k;
string s;
cin >> s;
s = " " + s;
for (int i = 2, j = 0; i <= n; kmp[i] = j, i++) {
while (j && s[i] != s[j + 1]) j = kmp[j];
if (s[i] == s[j + 1]) j++;
}
int x = kmp[n];
for(int i=1;i<=n;i++) cout<<s[i];
k--;
while(k--) for(int i=x+1;i<=n;i++) cout<<s[i];
}