天天看點

字元串--KMP模式比對算法

字元串的KMP模式比對算法的java實作

//通過計算傳回子串的next數組
    public int[] get_next(String string)
    {
        int[]next=new int[];
        char str[]=string.toCharArray();
        int i,j;
        i=;j=;
        next[]=;//j=1時的情況
        while (i<string.length())
        {
            if (j==||str[i]==str[j])
            {//str[i]表示字尾的單個字元,str[j]表示字首的單個字元
                i++;
                j++;
                next[i]=j;
            }else
            {
                j=next[j];//若字元不相同,則j值回溯
            }
        }
        return next;
    }
    //改進的KMP模式比對算法
    public int[] get_nextval(String string)
    {
        int[]next=new int[];
        char str_char[]=string.toCharArray();
        int i=,j=;
        next[]=;
        while (i<str_char.length)
        {
            if (j==||str_char[i]==str_char[j])
            {
                ++i;
                ++j;
                //下一個和前一個是否相等
                if (str_char[i]!=str_char[j])
                {
                    next[i]=j;//如果字首字元與字尾字元不同
                }
                else
                {
                    next[i]=next[j];//如果字首和字尾字元相同
                }
            }
            else {
                j=next[j];//字元不同,回溯
            }
        }
        return next;
    }
    //傳回子串在主串中第pos個字元之後的位置,若不存在則函數傳回值為0
    public int Index_KMP(String s,String string,int pos)
    {
        /**
         * KMP思想:知道子串中的前一個字元和後面的字元均不相等,而針對子串的第二位已經和主串中字元相等,
         * 就意味着子串的第一個字元不需要和主串中的第二個字元比較就知道他們是不可能相等,這樣可以省略不必要的比較
         * 主串的i值不回溯,即不可以變小,考慮變化的是子串的j值
         * j值得變化其實與主串沒什麼關系,關鍵就取決于子串的結構中是否有重複的問題
         * j的多少取決于目前字元之前的串的前字尾的相似度
         */
        char[] s_char=s.toCharArray();
        char[] str_char=string.toCharArray();
        if (str_char.length==)
        {//針對子串隻有一個字元元素的情況下
            for (int i=;i<s_char.length;i++)
            {//樸素模式比對方法
                if (str_char[]==s_char[i])
                    return i;
            }
            return ;
        }else
        {
            int i = pos;
            int j = ;
            int[] next = get_next(string);//對子串做分析得到next數組
            //int[] next=get_nextval(string);
            while (i < s_char.length && j < str_char.length) {
                //當小于主串、子串的長度時,循環繼續
                if (j ==  || s_char[i] == str_char[j])
                {//相等子串和主串同時向前
                    ++i;
                    ++j;
                } else
                {
                    //否則移動到子串相應位置
                    j = next[j];
                }
            }
            if (j >= str_char.length)
                //找到符合條件的子串,傳回其位置
                return i - str_char.length + ;
            else
                return ;//沒有找到,傳回0
        }
    }