KMP模式匹配

一、算法原理

一般匹配字符串时,我们从目标字符串str(假设长度为n)的第一个下标选取和ptr长度(长度为m)一样的子字符串进行比较,如果一样,就返回开始处的下标值,不一样,选取str下一个下标,同样选取长度为n的字符串进行比较,直到str的末尾(实际比较时,下标移动到n-m)。这样的时间复杂度是O(n*m)

KMP匹配的核心思想是利用之前判断过信息,通过一个next数组,保存模式串中前后最长公共子序列的长度,每次回溯时,通过next数组找到,前面匹配过的位置,省去了大量的计算时间。 

注意最长前缀:是说以第一个字符开始,但是不包含最后一个字符。
对于目标字符串ptr,ababaca,长度是7,所以next[0],next[1],next[2],next[3],next[4],next[5],next[6]分别计算的是 
aababaababababaababacababaca的相同的最长前缀和最长后缀的长度。由于aababaababababaababacababaca的相同的最长前缀和最长后缀是“”,“”,“a”,“ab”,“aba”,“”,“a”,所以next数组的值是[0,0,1,2,3,0,1]。

next数组就是说一旦在某处不匹配时,移动ptr字符串,使str的对应的最大后缀和ptr对应的最大前缀对齐,然后继续向后比较。

next数组的值,就是下次往前移动字符串ptr的移动距离。比如next中某个字符对应的值是4,则在该字符后的下一个字符不匹配时,可以直接移动往前移动ptr 4个长度,再次进行比较判别。

二、Java实现

1.获取next数组

public int[] getNext(String b)  
{  
    int len=b.length();  
    int j=0;  
    int next[]=new int[len+1];//next表示长度为i的字符串前缀和后缀的最长公共部分,从1开始  
    next[0]=next[1]=0; 
    for(int i=1;i<len;i++)//i表示字符串的下标,从0开始  
    {//j在每次循环开始都表示next[i]的值,同时也表示需要比较的下一个位置 
        while(j>0&&b.charAt(i)!=b.charAt(j))
            j=next[j];  
        if(b.charAt(i)==b.charAt(j))j++;  
        next[i+1]=j;  
    }  
    return next;  
} 

2.KMP算法

public void search(String original, String find, int next[]) {  
    int j = 0;  
    for (int i = 0; i < original.length(); i++) {  
        while (j > 0 && original.charAt(i) != find.charAt(j))  
            j = next[j];  
        if (original.charAt(i) == find.charAt(j))  
            j++;  
        if (j == find.length()) {  
            System.out.println("find at position " + (i - j));  
            System.out.println(original.subSequence(i - j + 1, i + 1));  
            j = next[j];  
        }  
    }  
}  


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值