小结论:
nxt[x]表示前0~x-1位存在的最长前缀=后缀的长度.
一个字符串长度为m, 那么最小循环节长度为m-nxt[m]
s串任意前缀的nxt数组就是s串的nxt数组, 直接用就行了
kmp的小技巧:
① 如果只看s中有没有t,kmp()循环加上当j==m时break的条件.
② 如果求出现次数, 要去掉①中的条件, 并每当j==m(匹配成功)时, 把j赋为nxt[j]
③ 如果求不重复的次数, 要去掉①中的条件, 并每当j==m(匹配成功)时, 把j赋为0(不再按kmp匹配, 直接将模式串头部移到下一位)
关于nxt数组的小技巧:
④ s串后面最少加几个能成循环串:
如果最小循环节长度x=0, 那么就要加一倍
如果|s|%x=0, 他已经是循环串了, 不用再加
|s|%x≠0, 缺多少补多少
⑤ 对于s的所有前缀, 前缀i是不是由某个串重复k(k>1)次构成
对于每个长度为pos的前缀, 求其最小循环节长度x, 若pos%x=0且pos/x>1那么这个0~pos-1的前缀就是合法的.
⑥ 给出串t, 问它最多能由多少个s构成, s为任意大小.
至少是1, s为t本身, 如果更短的s合法, 他一定是某个更长的s的一部分.
只要不断求当前串的最小循环节x, 若|t|%|x|==0就继续求nxt[x], 如果当前串不合法, 它的儿子更不可能合法.
⑦ 求串S的所有既是前缀又是后缀的字串长度.
若A是S的前缀&后缀, B是A的前缀&后缀, 那么B也会是S的前缀后缀.
用nxt[]即可求.
⑧ 给出S和T, 求最长的X, 既是S的前缀又是T的后缀.
S+T求nxt[len]是不行的, X可能会越过连接处.
S+'@'+T, 用特殊字符分隔即可.
⑨ 每个前缀出现次数的和.
cnt[pos]记录第pos个前缀x在比他长的前缀y中出现的次数,
递推式:
定义原串的前缀为x类串.
每个长度为a的x类串s会包含2个长度为nxt[a]的x类串t, 而两个相邻的s会有一个重复的t, 所以cnt[a]个s会有cnt[a]+1个t.
最后答案加上每个前缀本身共m. 具体见代码.