朴素的字符串匹配算法为什么慢? 因为它太健忘了,前一次匹配的信息其实可以有部分可以应用到后一次匹配中的,而朴素的字符串匹配算法只是简单的把这个信息扔掉,从头再来,因此,浪费了时间。好好的利用这些信息,自然可以提高运行速度。
1.问题描述
给定目标字符串 T[0..n-1] (基于 0 的数组,数组长度为 n ),和模式串 P[0..m-1] ,问 P 可否匹配 T 中的任意子串,如果可以,返回匹配位置。
2.问题分析
直观分析
brute-force 的蛮力法,适用于较小规模的字符串匹配。
优化
主要介绍 3 种优化办法,分别具体为: Rabin-Karp 算法,有限自动机和 KMP 算法。将分为 3 篇博文分别讨论。
3.算法描述
Rabin-Karp 算法。
Rabin-Karp 算法(以下简称为 RK 算法),是基于这样的思路:即把串看作是字符集长度进制的数,由数的比较得出字符串的比较结果。例如,给定字符集为∑ ={0,1,2,3,4,5,6,7,8,9} ,∑长度为 d=10 ,那么任何以∑为字符集的串都可看作 d (此处为 10 )进制的数。
记模式串 P[0..n-1] 对应的数值为 P , T[0..n-1] 所有长度为 m 的子串对应的数值为 ts ,设 P 和 T 都是基于字符集长度为 | ∑ |=d 的字符串。
那么, ts 即为 T[s..s+m] 对应的数值,这里 0<=s<=n-m-1 。
P = P[m]+d*(P[m-1]+d*(P[m-2]+..)))
同样 t0 也可类似求得。
最重要的是如何从 ts 求出 ts+1 。
ts+1 =T[s+m]+d*(ts -dm-1 *T[s])
注:此处是该算法的关键,即在常数时间内能够计算出下一个 m 长度的字串对应的数值。初看比较抽象,举个例子就比较明白了,设 x=12345 ,现在是已知长度为 3 的数值 234 ,现在要求 345 对应的数值,可以这样来得到: 345 = 5 + 10*(234-102 *2)
求出所有 m 长度子串所对应的数值,对数值进行比较,继而得出子串是否匹配。当模式串长度很大时,这时对应的数值会很大,比较起来比较麻烦,可使用对一个大奇数取模后进行比较。
4.具体实现
这里实现的只是m值较小时的情形,大整数需要特定的类的支持(如可自定义大整数类),选取10进制的数是为了方便起见,当然字母也是OK的。
#include <iostream>
using namespace std;
int getV(char p, const char* set)
{
for(int i=0; i<strlen(set); i++)
{
if (p==set[i])
return i;
}
return -1;
}
int RK(const char* T, const char* P,const char* set)
{
int base = strlen(set) ;
int n = strlen(T);
int m = strlen(P);
int h = 1;
for(int i=0;i<m-1;i++)
h*=base;
int p = 0;
int t = 0;
for(int i=0; i<m; i++)
{
p = base*p + getV(P[i],set);
t = base*t + getV(T[i],set);
}
for (int i=0; i<=n-m; i++)
{
cout<<"p,t is "<<p<<","<<t<<endl;
if (p==t) return i;
if (i<n-m)
t = getV(T[i+m],set)+base*( t - h*getV(T[i],set) );
}
return -1;
}
int main()
{
// set is the character set
const char* set= "0123456789";
const char* T = "258569236589780";
const char* P = "2365";
int i = RK(T, P, set);
cout<<"the postition is:"<<i<<endl;
return 0;
}
分享到:
相关推荐
**字符串匹配Rabin-Karp算法**是一种在文本中查找子串出现位置的高效算法,它由Rabin和Karp在1987年提出。在传统的字符串匹配算法中,如朴素算法,每次比较一个字符,如果发现不匹配则需要从头开始检查下一个位置,...
由于哈希函数可能会导致不同的字符串得到相同的哈希值(即哈希冲突),Rabin-Karp算法采用了滚动哈希的方式减少冲突。在比较过程中,当哈希值匹配时,只需要检查前缀和后缀的字符是否相同,而非重新计算整个模式串的...
Rabin-Karp 字符串搜索算法是基于哈希的字符串匹配算法,用于在一个文本中查找一个模式字符串的出现。下面是该算法的概念、特点、优缺点、适用场景和 Java 代码实现。 概念:Rabin-Karp 字符串搜索算法是一种基于...
"Rolling Hash(Rabin-Karp Algorithm)" Rolling Hash(Rabin-Karp ...Rabin-Karp算法的时间复杂度可以降低到O(n),使其成为一种高效的字符串搜索算法。该算法广泛应用于文本搜索、数据压缩和模式识别等领域。
本项目“StringMatch”专注于探究三种不同的字符串匹配算法:朴素算法、Rabin-Karp算法和KMP(Knuth-Morris-Pratt)算法。这三种算法在不同的场景下有着各自的优点和效率,理解它们的工作原理和性能差异对于优化搜索...
Rabin-Karp 算法是一种字符串搜索算法,由 Michael O. Rabin 和 Richard M. Karp 于 1987 年提出。该算法主要应用于在主字符串(大字符串)中查找子串(小字符串)是否存在,其特点是利用了数学的模运算来快速比较两...
Rabin-Karp算法,是由M.O.Rabin和R.A.Karp设计实现的一种基于移动散列值的字符串匹配算法。 通常基于散列值的字符串匹配方法:(1)首先计算模式字符串的散列函数;(2)然后利用相同的散列函数计算文本中所有可能...
在IT领域,字符串匹配是计算机科学中的一个基础且重要的问题,尤其在文本处理、搜索算法、数据挖掘等应用中有着广泛的应用。本毕业设计聚焦于三种经典的字符串匹配算法:RK算法、KMP算法和朴素算法,并用C#编程语言...
除了BM和KMP,还有许多其他的字符串匹配算法,如Boyer-Moore-Horspool算法(改进的BM),Rabin-Karp算法(使用哈希函数进行匹配),Sunday算法,以及AC自动机(Aho-Corasick算法)等。这些算法各有优缺点,适用于...
Rabin-Karp算法,一种字符串搜索算法,因其高效性和灵活性,在抄袭检测中得到了广泛应用。本文将深入探讨Rabin-Karp算法的原理,并介绍其在Java编程语言中的具体实现。 Rabin-Karp算法由Michael O. Rabin和Dick ...
通过改进Karp-Rabin 算法,实现了多模式字符串匹配技术,实验表明多模式Karp-Rabin算法具有良好的性能。随后在多模式Karp-Rabin 算法的基础上进一步改进,使其在高并发情况下能够支持模式串动态增删功能。实验表明该...
Rabin-Karp算法是一种字符串匹配算法,由Michael O. Rabin和Dick Karp于1987年提出。它的核心思想是通过哈希函数将较长的模式串和文本串转换为整数,然后比较这两个整数是否相等,以快速判断子串是否存在。这种方法...
运用Karp算法实现字符串匹配的c++程序
`Google-Palagrism-Checkmaster`项目巧妙地结合了JSoup的Web爬虫能力和Rabin-Karp算法的字符串匹配功能,创建了一个有效的抄袭检测工具。这种工具对于学术界、教育领域以及网络内容创作者来说具有很高的实用价值,...
这里我们关注的是一个基础且重要的算法——朴素的字符串匹配算法,也称为BF算法(Brute Force 算法)。 BF算法由D.E.Knuth和J.H.Morris以及V.R.Pratt分别独立提出,因此也被称为KMP算法的前身。它的主要思想是通过...
### 字符串匹配算法小集解析 #### 一、引言 本文档提供了一系列共35种不同的字符串匹配算法,这些算法在英文环境下被广泛讨论和应用。通过对这些算法进行详细的解析,我们可以更好地理解每种算法的特点、应用场景...
在实际应用中,我们可能需要结合其他技术,如动态规划、后缀数组、AC自动机等,来优化和改进字符串匹配算法,以适应不同的场景需求。例如,对于模糊匹配,可以使用Levenshtein距离来衡量两个字符串之间的差异,允许...
这里可以采用KMP算法或者Rabin-Karp算法来进行高效的字符串匹配,确保检索速度足够快。 #### 4.2 生物信息学中的应用 在基因测序中,需要将新的基因序列与已知数据库中的序列进行比对。这里可以使用后缀树或AC...
除了 Brute Force 算法外,还有许多其他的字符串匹配算法,如 Knuth-Morris-Pratt 算法、Rabin-Karp 算法、Boyer-Moore 算法等。 * Knuth-Morris-Pratt 算法是基于 Brute Force 算法的优化版本,它使用一个预处理的...
除了KMP算法,还有其他字符串匹配算法,如Boyer-Moore算法、Rabin-Karp算法等。它们各有特点,适用于不同的场景。比如Boyer-Moore算法利用坏字符规则和好后缀规则,比KMP更高效但实现相对复杂;Rabin-Karp算法则基于...