怕什么就要直面什么!我就要现在开始写题解!!!
题目描述
给定一个模式串S,以及一个模板串P,所有字符串中只包含大小写英文字母以及阿拉伯数字。
模板串P在模式串S中多次作为子串出现。
求出模板串P在模式串S中所有出现的位置的起始下标。
输入格式
第一行输入整数N,表示字符串P的长度。
第二行输入字符串P。
第三行输入整数M,表示字符串S的长度。
第四行输入字符串S。
输出格式
共一行,输出所有出现位置的起始下标(下标从0开始计数),整数之间用空格隔开。
数据范围1≤N≤105
1≤M≤106
输入样例:
3
aba
5
ababa
输出样例:
0 2
思路:
- 经典的kmp算法中最关键的就是求next数组了
- next数组的本质就是求相应长度子串的最大前缀后缀相同的值。
- 得到next数组以后,在重新匹配下一个环节的时候,能减少重新匹配的次数,也就是不用从头开始匹配。
- 举个例子来理解:
被匹配串 S=[ababcababefd]
模板串:P=[ababefd]
- 当匹配到下标为4的字符时,S[4]=‘c’,P[3+1]=‘e’,(下标分别从1和0开始)两者不匹配了,最朴素的做法是将P[0]对准S[1]从头开始匹配对吧?但是显然是不可能匹配成功的,KMP的做法就是让P[0]直接跳到S[2]开始匹配,才有可能配对成功。
- 为啥是S[2]呢?这个时候其实就是从P的next[3]=2的来的 ,再来深化一下next求的是P子串里面前缀后缀相等的最大长度:
P的子串 | 最大匹配前缀 | 最大匹配后缀 | next数组 |
---|---|---|---|
a | \ | \ | next[0]=0 |
ab | a | b | next[1]=0 |
aba | a | a | next[2]=1 |
abab | ab | ab | nect[3]=2 |
ababe | \ | \ | next[4]=0 |