实现方法有很多,简单介绍一种
ababababab
0012345678
abababa
abababa
ababa
ababa
aba
aba
a
a
ababababcdddddd
ababababab
0012345678
ababababab
abacabadabacaba
001012301234567
abacabadabacabad
0010123012345678
abacabadabacabac
0010123012345674
abacabadabacabab
0010123012345672
abacabadabacabaa
0010123012345671
abacabadabacabae
0010123012345670
对于每个前缀 s[1..i]
找到最长的前缀等于后缀的长度p[i](不能是整个前缀
p[i] < i
s[1..p[i]] == s[i-p[i]+1..i]
长度为p[i]的前缀 以i结尾长度为p[i]的后缀
最长的是p[i]
如果希望找到所有合法的解
p[i]
p[p[i]]
p[p[p[i]]]
....
直到0
一些人的定义/实现,在求p[i]时,不仅要求
s[1..p[i]] == s[i-p[i]+1..i]
还要求s[p[i]+1] != s[i]
这是没有必要的,我们不采用这种写法
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaab
aaaaaaaaab
aaaaaaaaab
abcabcabcabcabcabc
abcabcabc
abcabcabc
abcabcabc
abcabcabc
abcabcabc
abcabcabc
#include <bits/stdc++.h> using namespace std; char s[1000020]; char t[1000020]; int p[1000020]; int main() { scanf("%s", s + 1); scanf("%s", t + 1); int n = strlen(s + 1); int m = strlen(t + 1); int u = 0; for (int i = 2; i <= m; i++) { while (u > 0 && t[u + 1] != t[i]) { u = p[u]; } if (t[u + 1] == t[i]) { u++; } p[i] = u; } u = 0; for (int i = 1; i <= n; i++) { while (u > 0 && t[u + 1] != s[i]) { u = p[u]; } if (t[u + 1] == s[i]) { u++; } if (u == m) { printf("%d\n", i - m + 1); u = p[u]; // 找到的匹配允许有重叠 // u = 0; // 找到的匹配不允许有重叠 } } for (int i = 1; i <= m; i++) { printf("%d%c", p[i], i == m ? '\n' : ' '); } }
cabcabca
00012345
bca
bca
ca
寻找最长的周期
不能是整个串本身
babababa 6
bababa
bababab 6
bababa
bababa 4
baba
babab 4
baba
baba 2
ba
bab 2
ba
ba 0
ba
b 0
#include <bits/stdc++.h> using namespace std; char s[1000020]; int p[1000020]; int f[1000020]; int n; long long z; int main() { scanf("%d", &n); scanf("%s", s + 1); int u = 0; f[1] = 1; for (int i = 2; i <= n; i++) { while (u > 0 && s[u + 1] != s[i]) { u = p[u]; } if (s[u + 1] == s[i]) { u++; } p[i] = u; f[i] = i; if (p[i] > 0) { f[i] = f[p[i]]; } z += i - f[i]; } printf("%lld\n", z); return 0; }
对于每个位置,按照p[i]往0跳,f[i]是最后一步是从多少跳到0的
http://acm.hdu.edu.cn/showproblem.php?pid=1711
输入两个数字串匹配,找到第一次匹配的位置。
将KMP算法由字符串,推广到一般的数字序列。
http://acm.hdu.edu.cn/showproblem.php?pid=2087
输入两个字母串匹配,问第二个在第一个中出现多少次。
字符串匹配,求匹配到的子串个数,不能重叠,问最多匹配多少个。
比如aaaaaaaaa中包含3个aaa,而不是7个。
http://acm.hdu.edu.cn/showproblem.php?pid=2594
找到最长的一个字符串,既是第一个串的前缀,又是第二个串的后缀。
连接起来,求next数组。
http://poj.org/problem?id=3461
字符串匹配,求匹配到的子串个数,可以重叠
http://poj.org/problem?id=2406
输入一个字符串求最小循环节,实际输出最小循环节的次数。
对于字符串计算next数组,考虑n-next[n]是否是n的约数。
https://beta.atcoder.jp/contests/arc060/tasks/arc060_d
输入一个字符串,分成尽量少的段,使得每段没有循环节。
输出最小段数,和方案数。
只有三种情况