lotus

贵有恒何必三更眠五更起 最无益只怕一日曝十日寒

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

 

 

/**
 * rk字符串匹配算法,主要引入了hash的概念,
 * 利用子串的hash值依次对比主串相应长度的子串hash值
 * 并对hash值相同的子串进行匹配对比
 */
public class RKSearch {

    /**
     * rk算法入口
     * @param t 主字符串
     * @param p 子字符串
     * @return
     */
    public int rk(String t,String p){
        // 字符串非法判定
        if (t == null||t.length() == 0 || p == null || p.length() == 0 || p.length() > t.length()){
            return -1;
        }
        // 计算子串hash值
        int hash = hash(p,26,31,0,p.length());
        for (int i = 0;i< t.length();i++){
            // 对主串内的数字一次进行hash计算,并对比子串是否匹配
            if (hash(t,26,31,i,p.length()) == hash && match(t,p,i)){
                return i;
            }
        }
        return -1;
    }

    /**
     * 自定义hash算法
     * @param str
     * @param r 进制数
     * @param k 将字符串映射到k的范围
     * @param start 从str串的开始位置
     * @param len 子串的长度
     * @return
     */
    private int hash(String str,int r,int k,int start,int len){
        int hash = 0; // 设定hash值为0
        /**
         * 对字符串内的每个字符串进行计算
         */
        for (int i = start;i<start+len;i++){
            // 进制系数 与 hash 的积 + 每个字符与范围取余的结果
            hash = (r * hash + str.charAt(i) % k);
        }
        // 将最后的结果,映射到指定范围内
        return hash % k;
    }

    /**
     * 对于hash计算结果相同的两个子串,是否匹配的比较
     * 主要判定hash冲突情况下的匹配问题
     * @param t 主串
     * @param p 子串
     * @param i 从主串下标为i的地方开始比较
     * @return
     */
    private boolean match(String t,String p,int i){
        for (int j = 0 ; j < p.length();j++){
            if (p.charAt(j) != t.charAt(j + i)){
                return false;
            }
        }
        return true;
    }

    public static void main(String[] args) {
        String test = "adbsasdfddddsasdffesase";
        String sub = "sd";
        RKSearch rkSearch = new RKSearch();
        int rk = rkSearch.rk(test, sub);
        System.out.println(rk);
    }
}

 

posted on 2022-12-26 23:27  白露~  阅读(101)  评论(0编辑  收藏  举报