1 问题描述
在进行字符串操作的时候,我们有一个需求,从给定的一个主串s=s0s1...sm−1s=s_0s_1...s_{m-1}s=s0s1...sm−1中查找是否包含了某个模式串t=t0t1...tn−1t=t_0t_1...t_{n-1}t=t0t1...tn−1,并返回模式串在主串中首次出现时的第一个字符在主串中的位置。用接口描述为 int indexOf(String str, int start);
调用时,int index = subStr.indexOf(str, start);
这样就可以返回subStr子串在str中的起始位置了。
2 理论分析
最简单的实现方法就是暴力搜索Brute-Force:将模式串作为滑动窗口在主串上每滑动一格,然后将主串对应的字符依次与模式串比较。遇到第一个不匹配就将窗口向后滑动一格,模式串指针回退到0,主串指针与模式串对应,又依次比较,直到找到与模式串完全匹配的位置返回,若没有找到返回-1。这种方法实现简单,缺点是时间复杂度较高,为O(m×n)O(m\times n)O(m×n),而KMP算法的时间复杂度仅为O(m+n)O(m + n)O(m+n)。
KMP算法核心思想:当某次匹配失败(sis_isi /= tjt_jtj)时,主串sss的当前比较位置iii不必回退,此时主串中的sis_isi可直接和模式串某个tk(0<k<j)t_k(0<k<j)tk(0<k<j)进行比较,此处下标kkk的确定与主串无关,只与模式串本身的构成有关,即从模式串本身就可计算出kkk的值。
理论分析:设主串s=s0s1...sm−1s=s_0s_1...s_{m-1}s=s0s1...s