题目所属分类
属于典型的KMP算法
原题链接
代码案例:输入样例:
3
aba
5
ababa
输出样例:
0 2
题解
KMP的朴素做法
解释next[i]=j的含义 可以把j当作常数那么看
理解j=ne[j],首先我们需要理解ne[i]=j
ne[i]=j表示:ne[i]表示当有i个字符时最大前缀后缀的共同元素个数为j
理解j=next[j]
如果说单说模板串p 而言 那么j那点的坐标就是等于next[j]
那就可以理解为匹配最长公共前后缀的下标为next[j]
因为需要三段相等 所以j那个点就等于next[j]
1和3相等意思就是next的含义 而我们希望移动到下一个匹配的地方
也就是直接让1和2相等
s[ a , b ] = p[ 1, j ] && s[ i ] != p[ j + 1 ] 此时要移动p串(不是移动1格,而是直接移动到下次能匹配的位置)
其中1串为[ 1, next[ j ] ],3串为[ j - next[ j ] + 1 , j ]。由匹配可知 1串等于3串,3串等于2串。所以直接移动p串使1到3的位置即可。
这个操作可由j = next[ j ]直接完成。 如此往复下去,当 j == m时匹配成功。
这时候可以看成
for(int i = 1, j = 0; i <= n; i++)
{
//j不能退回起点
while(j > 0 && s[i] != p[j+1]) j = ne[j];
//如果j有对应p串的元素, 且s[i] != p[j+1], 则失配, 移动p串
//用while是由于移动后可能仍然失配,所以要继续移动直到匹配或整个p串移到后面(j = 0)
if(s[i] == p[j+1]) j++;
//当前元素匹配,j移向p串下一位
if(j == n)
{
//匹配成功,进行相关操作
j = next[j]; //继续匹配下一个子串
}
}
求next数组的过程(详细版见)
for(int i = 2, j = 0; i <= m; i++)
{
while(j > 0 && p[i] != p[j+1]) j = next[j];
if(p[i] == p[j+1]) j++;
next[i] = j;
}
完整注释代码如下
输出没用BufferedReader总是显示超时
import java.io.*;
public class Main{
static int N = 100010,M = 1000010;
static char[] p = new char[N];
static char[] s = new char[M];
static int[] ne = new int[N];
public static void main(String[] args)throws <