KMP算法

来源:互联网 发布:剑网三大师捏脸数据 编辑:程序博客网 时间:2024/06/05 18:01

 最近看算法吧 看到一个题目 用到KMP算法 然后就找了些资料  最后发现一个 很不错的博客 这么好的东东 到现在才知道  敲打

http://www.matrix67.com/blog/archives/115   里面讲的东西很厉害 很牛叉! 就拿这个kmp算法来说 通俗易懂!  看了这篇文章的大致思想 自己整了个代码!

 

 

package com.sinitek.trading.program.client.interest;/** * Created with IntelliJ IDEA. * User: xn-hyao-01 * Date: 13-11-4 * Time: 下午3:12 * To change this template use File | Settings | File Templates. */public class KMP {    public static void main(String[] args) {        getIndex("abcdabcdabceabce");        kmp("abcdefghijk12k123fef", "k123");    }    public static void kmp(String source, String str) {        //获取 匹配下标        int[] points = getIndex(str);        //字符串长度        int sourceLength = source.length();        //str字符串长度        int strLength = str.length();        //i是source的索引 j是str的索引        int j = 0, i;        //循环进行匹配        for (i = 0; i < sourceLength && j < strLength; i++, j++) {            if (source.charAt(i) == str.charAt(j)) {                 //匹配则进行下一个匹配            } else {                //匹配失败 并且当前匹配的不是第2个 就是说已经至少有一个匹配成功了 所以可以找到最后一个匹配的覆盖下标 覆盖然后进行下轮匹配                if (j > 0) {                    //因为还是当前字符比较 所以先减一 外面再加1就ok了                    i--;                    //让j指向最后一个匹配成功的 覆盖下标                    j = points[j - 1];                } else {                    //如果匹配失败 且是第一个 所以要重新匹配 把j=-1那么 下次就是重新匹配                    j--;                }            }        }        //打印        System.out.print(j + "   " + i);    }    /**     * 获取当前下标是最后一个匹配的成功的(下一个是匹配失败的  所以要往前挪,怎么挪呢 当然是覆盖原来的  比如已经匹配的是abcdabc 那么显然接下来 我们应该用abc去匹配后面的abc 而用d去进去尝试匹配刚才未匹配成功的那个)     *     * @param str     * @return 返回如果当前是最后一位匹配的时候 应该用什么跟当前的进行匹配没有的话返回-1 有的话返回跟当前匹配的下标 (取的是最大匹配)     */    public static int[] getIndex(String str) {        //字符串长度        int length = str.length();        //返回 下次匹配的下标        int[] points = new int[length];        //如果最后一个匹配的下标是0 那么显然没有什么可以去覆盖第一个了 所以只能是-1(只要1个成功匹配 那么要覆盖也只能是自己覆盖自己 自己覆盖自己 还是第2个去匹配 显然不成功 所以是-1 )        points[0] = -1;        //第一个匹配是-1 所以可以直接初始化        int point = -1;        //进行遍历        for (int i = 1; i < length; i++) {            //默认是无法覆盖的            points[i] = -1;            //上一个的匹配是 point  那么如果当前跟point+1 匹配 则可以得到最大匹配是 point+1;            if (str.charAt(i) == str.charAt(point + 1)) {                //匹配 则将该下标的最大匹配设置为 前一个的匹配值加1                points[i] = point + 1;                //因为匹配成功了 所以下一个尝试的 前一个就是当前的了 所以point重置                point = point + 1;            } else {                /*如果匹配失败point=-1是说明跟第一个都没匹配 所以不可能再匹配了 直接是-1   如果不为-1则可以 进一步匹配 递归型的                   abcdefgabcdefgabc                          abcdefgabc                                 abc                */                if (point > -1) {                    //因为还是查找当前下标的匹配值 但是外面会加1 所以先减一                    i--;                    //重置point                    point = points[point - 1];                }            }        }        //打印        for (int i : points) {            System.out.print(" " + i);        }        System.out.println();        return points;    }}

 

看不懂的可以去看看推荐的那个博客!  讲的很清楚!

原创粉丝点击