KMP学习笔记
前言:
重温一遍KMP,为接下来的AC自动机做准备!
KMP算法:
KMP算法是一种改进的字符串匹配算法,由D.E.Knuth,J.H.Morris和V.R.Pratt提出的,因此人们称它为克努特—莫里斯—普拉特操作(简称KMP算法)。
看上去依旧很高大上,但是其实又是一种简单的方法
首先回顾一下暴力匹配:
虽然看上去暴力也很好,但其实这有一个很大的弊病:
回溯之后必然导致无法配对
这就吧把时间弄的很慢
这是我们便引入了KMP
如果j = -1,或者当前字符匹配成功(即S1[i] == S2[j]),都令i++,j++,继续匹配下一个字符;
如果j != -1,且当前字符匹配失败(即S1[i] != S2[j]),则令 i 不变,j = next[j]。此举意味着无法匹配时,S2相对于S1向右移动了j - next [j] 位。
而next数组又是什么呢?
next表示除当前字符最长相同的前缀后缀
怎么求呢?
void get_next() { int len1=strlen(s2); next[0]=-1; int k=-1; int j=0; while(len1-1>j) { if((k==-1)||(s2[j]==s2[k])) { j++,k++; if(s2[j]!=s2[k]) { next[j]=k; } else { next[j]=next[k]; } } else { k=next[k]; } } }
当next求出来了,KMP的思路也明了了:
void kmp() { long long i=0,j=0,len1=strlen(s1),len2=strlen(s2); while(i<=len1-1) { if((j==-1)||(s1[i]==s2[j])) { i++,j++; } else { j=next[j]; } if(j==len2) { printf("%lld\n",i-j+1); } } }
加油!