/**
* 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);
}
}
10-09
1709
![](https://csdnimg.cn/release/blogv2/dist/pc/img/readCountWhite.png)
07-29