剑指offer

13_KMP字符匹配算法

2020-05-19  本文已影响0人  是新来的啊强呀

要求:{A,B,A,B,C,A,B,A,A}=> {'A','B','A','B','A','B','A','B','C','A','B','A','A','B'},找出匹配的字符串在原始的第几位。
讲解推荐

思路:使用kmp字符匹配算法,kmp算法的核心思想是利用比对失败的信息,减少模式串与目标串的比对次数.
0、利用需要匹配的字符串,求出前缀表,计算prefix数组,采用动态规划
1、把计算出来的前缀表往后移动一格,最后一位不要,prefix[0]=-1
2、进行字符匹配

public class L13_KMLP{
    // 第一步,求前缀表
    public static int[] Prefix(char[] arr){
        int j = 0;
        int i = 1;
        int n = arr.length;
        // suffix(S): S的所有后缀的集合
        // prefix(S): S的所有前缀的集合
        // prefix[i]代表的意义是suffix(c[1]c[2]......c[i])与prefix(c[1]c[2]......c[i])两个集合中最长相同串的长度
        int[] prefix = new int[n];
        prefix[0] = 0;
        while(i<n){
            // 求第i行的前缀数
            if(arr[j] == arr[i]){
                // 遇到相等,加一
                prefix[i] = j+1;
                j++;
                i++;
            }else {
                if(j>0){
                    j = prefix[j-1];
                } else{
                    prefix[i] = j;
                    i++;
                }

            }
        }
        return prefix;
    }
    // 第二步,前缀表后移一位,并给prefix[0]赋-1;
    public static int[] Move_prefix(int[] arr){
        int[] newarr = new int[arr.length];
        for(int i = 1, j =0; i < arr.length; i++,j++){
            newarr[i] = arr[j];
        }
        newarr[0] = -1;
        return newarr;
    }

    // 进行字符匹配
    public static void kmp_search(char[] text, char[] pattern){
        int i = 0;  // text上的指针
        int j = 0;  // pattern上的指针

        int[] pf = Prefix(pattern);
        int[] prefix = Move_prefix(pf);
        int m = text.length;  // text的长度
        int n = pattern.length;  // pattern 的长度
        while(i<m){
            // text最后一位匹配成功
            if(j==n-1 && text[i] == pattern[j]){
                System.out.printf("Fount pattern at %d\n", i-j );
                j = prefix[j];
            }
            // 往后移动,匹配遇到不相等的将j指向prefix[j]位置
            if(text[i] == pattern[j]){
                i++;
                j++;
            }else{
                j = prefix[j];
                // 如果j指向了第一位
                if(j == -1){
                    i++;
                    j++;
                }
            }
        }

    }
    public static void main(String[] args) {
        char[] arr ={'A','B','A','B','A','B','A','B','C','A','B','A','A','B'};
        char[] pattern = {'A','B','A','B','C','A','B','A','A'};
        kmp_search(arr,pattern);
    }
}
上一篇下一篇

猜你喜欢

热点阅读