KMP
- 一位位扫过T,维护最长能匹配S的那个前缀
- 能匹配的时候直接把匹配的位置+1
- 失配的话就回去
两个过程,先自我匹配求出next数组,然后在和匹配串匹配。
Code
next[0]=now=-1;
for (int i=1,j=-1;i<=s2.size()-1;i++){
while (j>=0&&s2[j+1]!=s2[i]) j=next[j];
if (s2[i]==s2[j+1]) j++;
next[i]=j;
}
for (int i=0,j=-1;i<=s1.size()-1;i++){
while (j>=0&&s1[i]!=s2[j+1]) j=next[j];
if (s1[i]==s2[j+1]) j++;
if (j==s2.size()-1) printf("%d\n",i-s2.size()+2),now=next[now];
}
.
KMP自动机
我们可能希望直接指导在
s
[
1..
i
]
s[1..i]
s[1..i]后面加c能得到什么而不是每次都去跳fail(尽管不会影响复杂度),设其为
t
r
a
i
n
[
i
]
[
c
]
train[i][c]
train[i][c]
如果
s
[
i
+
1
]
=
=
c
则
t
r
a
n
s
[
i
]
[
c
]
=
i
+
1
s[i+1] == c 则trans[i][c] = i+1
s[i+1]==c则trans[i][c]=i+1
否则就为
t
r
a
n
s
Z
[
n
e
x
t
[
i
]
]
[
c
]
transZ[next[i]][c]
transZ[next[i]][c]
- 这样好像可以直接搞了
- 听得有点迷
卷积求匹配
- 。。什么东西
- 听了老师推了一大波公式,似乎直接迷了。
- 数学功底不够啊。。。。。
AC自动机
- 将KMP的过程套在trie上
- 笔记来不及几记了
exkmp
ex[i]表示T和S的最长公共前缀
exkmp的过程能在
O
(
n
)
O(n)
O(n)内求出ex数组
- 设next[i]表示T和 T [ 1.. n ] T[1..n] T[1..n]的最长公共前缀
- 如何推?
- 不知道。。。
哈希
- 用小手段来判断两个串是否相同
- 通过自然溢出或者模一个大质数来得到
- 令:
f i = ∑ j = 1 i s j ∗ b j f_i = \sum_{j=1} ^i s_j*b^j fi=j=1∑isj∗bj - 然后通过一堆下操作就能哈希了
- 最好双哈希,能提高准确率
- 二分 + 哈希可以 O ( n ) O(n) O(n)预处理, O ( l o g n ) O(logn) O(logn)求最长公共前缀
例题:
bzoj 3942
- 对T求一个 n e x t next next数组
- 把s拿出来一位位匹配
- 维护一个栈, f [ i ] f[i] f[i]表示这一位匹配到 t t t的第几位
- 没了??
bzoj 4974
- 逆推kmp的过程
- 根据next一直跳是否为0进行判断
- 若为0 ,放一个最小字符,否则就是next的字符
poj …
- 扫每一行、每一列,做一遍kmop
- 可得到每一行。每一列的循环节
- *一 * 即可
hdu 6153
- 将s2反一反
- 求一遍kmp
- 将贡献求出即可
poj 3167
- kmap匹配不看字符是否相同,而是看相对大小关系、
bzoj2938
- 是AC自动机模板??
- 哎有挂了
动物园
- 设 c n t i cnt_i cnti表示长为i的 b o r d e r border border的个数
- 维护两个指针,一个指向长度最长的 b o r d e r border border的个数,另一个是长度> 1 2 i \frac 12i 21i的 b o r d e r border border个数
- 然后。然后。。没了??!!!
Bzoj 3172
- 直接上AC自动机
- 把沿途经过的点标记一下,然后求一下fail,也许吧。。
- ????
bzoj 3097
- 这道题是卡自然溢出哈希
- 如果base是偶数,直接用 b a a a a a a a . . . . . . ( 64 个 a ) baaaaaaa......(64个a) baaaaaaa......(64个a), a a a a a a a a a a a a a . . . a a aaaaaaaaaaaaa...aa aaaaaaaaaaaaa...aa即可
- 如果为奇数,就是需要推一波公式
- 没懂