天天看点

字符串--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
        }
    }