KMP算法

 最近看算法吧 看到一个题目 用到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;
    }
}

 

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值