期望时间复杂度 O(n + m),极限 \(O(nm)\)。
首先输出若干行,每行一个整数,按从小到大的顺序输出 \(s_2\) 在 \(s_1\) 中出现的位置。
最后一行输出 \(\lvert s_2 \rvert\) 个整数,第 \(i\) 个整数表示 \(s_2\) 的长度为 \(i\) 的前缀的最长 \(border\) 长度。
#include <bits/stdc++.h>
using namespace std;
#define LL long long
int main(){
ios::sync_with_stdio(false);cin.tie(0);
string s, t;
cin >> s >> t;
int n = s.size(), m = t.size();
vector <int> nxt(m + 1);
s = '-' + s;
t = '-' + t;
for (int i = 2, j = 0; i <= m; i ++ ){
while(j && t[i] != t[j + 1]) j = nxt[j];
if (t[i] == t[j + 1]) j ++ ;
nxt[i] = j;
}
for (int i = 1, j = 0; i <= n; i ++ ){
while(j && s[i] != t[j + 1]) j = nxt[j];
if (s[i] == t[j + 1]) j ++ ;
if (j == m){
cout << i - m + 1 << "\n";
j = nxt[j];
}
}
for (int i = 1; i <= m; i ++ )
cout << nxt[i] << " \n"[i == m];
return 0;
}
洛谷模板: https://www.luogu.com.cn/problem/P3375
Acwing模板:https://www.acwing.com/problem/content/833/
应用:
1.在字符串中查找子串
2.最小周期:字符串长度-整个字符串的border
3.最小循环节:区别于周期,当字符串长度 \(n \% (n - nxt[n]) == 0\) 时,等于最小周期,否则为 \(n\)