数据结构与算法

串--模式匹配算法

2019-12-22  本文已影响0人  暮想sun

BF算法--朴素匹配算法(暴力匹配算法)

主串中,检查起始位置分别是 0、1、2…n-m 且长度为 m 的 n-m+1 个子串,看有没有跟模式串匹配的。O(n*m)

public int bf(char[] masterChar, char[] matchChar) {
        //目标数据从第一个开始比对
        char first = matchChar[0];
        //剩余最大长度,从0开始比较到max时,没有匹配到数据,就不用匹配了,后边数据长度不够
        int max = masterChar.length - matchChar.length;

        //for循环的含义为,继续寻找下一个匹配第一个字符的下标
        for (int i = 0; i <= max; i++) {
            //
            if (masterChar[i] != first) {
                while (++i <= max && masterChar[i] != first) {

                }
            }

            //碰到数据与first相等,此时下标为i
            if (i <= max) {
                //继续匹配i下一个元素与target元素匹配
                int j = i + 1;
                int end = j + matchChar.length - 1;
                for (int k = 1; j < end && masterChar[j]
                    == matchChar[k]; j++, k++) {

                }

                //如果顺利匹配到最后一位且成功,则匹配成功
                if (j == end) {
                    return i;
                }
            }
        }
        return -1;
    }

KMP模式匹配算法:

在模式串和主串匹配的过程中,把不能匹配的那个字符仍然叫作坏字符,把已经匹配的那段字符串叫作好前缀。
好前缀的所有后缀子串中,最长的可匹配前缀子串的那个后缀子串,叫作最长可匹配后缀子串;对应的前缀子串,叫作最长可匹配前缀子串。


public static int kmp(char[] masterChar, char[] matchChar) {

        //获取到最长前缀子串数组
        int[] next = getNext(matchChar);
        int j = 0;
        for (int i = 0; i < masterChar.length; ++i) {
            // 一直找到a[i]和b[j]
            while (j > 0 && masterChar[i] != matchChar[j]) {
                //比较的是第j个数据,如果数据不等,则需要找到。前面数据的最长可匹配子串的下一个字符,是否相等。
                j = next[j - 1] + 1;
            }
            if (masterChar[i] == matchChar[j]) {
                ++j;
            }
            // 找到匹配模式串的了
            if (j == matchChar.length) {
                return i - matchChar.length + 1;
            }
        }
        return -1;
    }
    private static int[] getNext(char[] matchChar) {
        int[] next = new int[matchChar.length];
        next[0] = -1;
        int k = -1;
        for (int i = 1; i < matchChar.length; ++i) {
            //如果上一个匹配的字符的下一个字符,没有等于要匹配的下一个字符。
            // 则在上一个字符能找到的最长前缀子串中,找到最长前缀子串。判断最长前缀子串的下一个字符是不是与其匹配
            while (k != -1 && matchChar[k + 1] != matchChar[i]) {
                k = next[k];
            }
            if (matchChar[k + 1] == matchChar[i]) {
                ++k;
            }
            next[i] = k;
        }
        return next;
    }
上一篇 下一篇

猜你喜欢

热点阅读