面试官问:你知道什么是KMP算法吗?说说你对KMP算法的理解。
答:KMP算法是用来进行字符串匹配查找的,比如在字符串1中查找是否包含字符串2。核心是先求出Next数组。什么是next数组?我的理解是:
next数组表示的是待查找的字符串的最大公共前后缀中的公共前缀的最后一个字符的下标,知道这个下标,就可以知道当匹配目标字符串出错时,目标字符串的指针怎么回退,而查找段落的指针不用回退,这样遍历一遍查找段落,就可以知道是否存在目标字符串,时间复杂度为O(n)
例如,求目标字符串ababc的next数组,下标从0开始。
比如next[2],2位置为a,则next[2]表示0位置的a(因为aba的最长公共前缀为a),next[2] =0。
比如next[3],3位置为b,则next[3]表示1位置的b(因为abab的最长公共前缀为ab), next[3] = 1。
比如next[4],由于4位置为c,而ababc没有公共前后缀,则next[4]=-1。
那么什么是最长公共前后缀,为什么需要它和next数组?这里我解释下它的原理:
- 比如需查找字符串"ababc",子串ab最长公共前后缀长度为0(因为a和b不等),子串aba最长公共前后缀长度为1(a的长度,首和尾都有a), 字串abab最长公共前后缀长度为2(ab的长度,首和尾都有ab),ababc最长公共前后缀长度为0(首和尾不同)。
- 在子串1“abababc”中查找子串2"ababc",对照看下图:当我们匹配到第五位时,发现a和c不相等,如果没有这个next数组,我们需要重新比对子串1的第2位(指针从第5位回到第2位)和子串2的第1位。有了这个next数组,我们知道错误匹配字母c前面的abab最大公共前后缀长度为2,所以我们可以直接右移子串2两位,比对子串1的还是第五位和子串2的第3位。这样的匹配算法,字串1中的指针不用回退,等于只要遍历一遍字串1就可以查到是否包含字串2,时间复杂度位O(n)
- next数组求法代码为:
public void getNext(String needle,int next[]){
//规定长度为1的字符串没有最长公共前后缀
next[0]=-1;
char []arr=needle.toCharArray();
int strLen=arr.length;
for(int i=1;i