Robin-Karp algorithm 字符串的匹配

有关字符串的匹配问题,有很好的算法,即KMP算法,但是还有一种其实经常使用到的算法是Rabin-Karp算法,它是使用hash的原理来进行字符串匹配的。具体的做法如下。

Rabin-Karp算法是由Rabin和Karp提出的一个在实际中有比较好应用的字符串匹配算法,此算法的预处理时间为O(m),但它的在最坏情况下的时间复杂度为O((2n-m+1)m),而平均复杂度接近O(m+n),此算法的主要思想就是通过对字符串进行哈稀运算,使得算法可以容易的排除大量的不相同的字符串,假设模式字符串的长度为m,利用
Horner法则p = p[m] + 10(p[m -1] + 10(p[m-2]+...+10(p[2]+10p[1])...)),求出模式字符串的哈稀值p,而对于文本字符串来说,对应于每个长度为m的子串的哈稀值为t(s+1)=10(t(s)-10^(m-1)T[s+1])+T[s+m+1],然后比较此哈稀值与模式字符串的哈稀值是否相等,若不相同,则字符串一定不同,若相同,则需要进一步的按位比较,所以它的最坏情况下的时间复杂度为O(mn)。

Rabin-Karp is a good example of a randomized algorithm(if we pick M in some random way).We get no guarantee the algorithm runs in O(n+m)time, because we may get unlucky and have the hash values regularly collide with spurious mathces. Still, the odds are heavily in out favor-if the hash function returns values uniformly from 0 to M-1, the probability of a false collision should be 1/M.This is quite reasonable:ifM=.n,there should only be one false collision per string.and if M = n^k for k>=2, the odds are greate we will never see any false collisions.

转载于:https://www.cnblogs.com/feng9exe/p/10003411.html

Rabin-Karp 是一种高效的字符串匹配算法,其核心思想是通过“滚动哈希”来减少不必要的字符比较次数。相比传统的暴力搜索(逐一比对每个位置是否匹配目标模式串),Rabin-Karp 可以更快地排除不可能匹配的位置。 ### 核心原理 1. **哈希值预计算**:首先为待查找的目标模式串生成一个唯一的数值表示形式 —— 即所谓的 “指纹”,也叫作哈希码。 2. **文本分块并求哈希**:接着把主文中相应长度的每一块都转换为其对应的哈希码。 3. **快速筛选候选区段**:只有当某一段文字片段的哈希值与给定模板相同时才做进一步详细验证确认两者完全一致;而其余大部分情况无需逐字母去核实即可判定不符。 这种方法极大地提高了效率特别是面对大型文件或多组查询任务时尤为显著因为一旦建立了合适的散列函数之后每次新的请求都可以复用之前的工作成果而不是每次都得重新开始扫描整个文档内容。 不过值得注意的是尽管RK算法理论上看起来很美好但在实际应用过程中可能会遭遇到两个主要挑战分别是: - *碰撞概率* : 即使使用良好的hash function也无法保证绝对不会有false positive的情况发生所以最终仍然需要确切对比疑似结果; - 对于特殊类型的输入比如大量重复短序列等可能导致性能下降接近普通穷举法水平因此选择适当的参数以及结合具体情况调整策略非常重要. --- ### 示例代码 (JAVA) 下面是一个简单的 Rabin Karp 实现例子: ```java public class RabinKarp { private static final long Q = 101; // A prime number used as modulus to avoid overflow. public boolean search(String pattern, String text){ int M = pattern.length(); int N = text.length(); /* Preprocess */ long pHash=computeHash(pattern,M); long tHash=computeHash(text.substring(0,M),M); if(pHash ==tHash && compareStrings(pattern,text.substring(0,M))) return true; for(int i=M;i<N;i++){ char leftChar=text.charAt(i-M); char rightChar=text.charAt(i); // Remove contribution of the oldest character and add newest one's impact on hash value. tHash=(tHash-leftChar*(long)Math.pow(d,M-1))*d +rightChar ; tHash%=Q ; if(tHash<0)tHash+=Q ; if(pHash==tHash&&compareStrings(pattern ,text.substring(i-M+1,i+1))){ return true; } } return false; } private double computeHash(String s,int len){ long h=0,d=256;// Assuming ASCII characters only thus base is set at 256 here. for(int j=0;j<len;j++) h=(h*d+s.charAt(j))%Q; return h; } private Boolean compareStrings(String x,String y){ if(x.equals(y)) return true; else return false; } } ``` 上面这个版本实现了基本功能但是为了简化演示忽略了部分边界条件处理例如空格或大小写的敏感度等问题可以根据需求添加更多健壮性的检查机制.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值