Rabin-Karp-MATCHER字符串匹配算法; 一种效率还不错的匹配算法; 思想是关键.

来源:互联网 发布:轻松软件管理平台 编辑:程序博客网 时间:2024/04/29 06:41

 

 

描述一下算法的思想:

 

朴素的字符串匹配, 是对文本串T的每一位开始的子串与模式串P进行匹配, 一共有n-m+1位, 每次最坏扫描m位, 所以复杂度O(n(n-m+1))

 

RabinKarp算法是怎么优化这个过程的呢?

 

首先, 讲朴素的字符串匹配变的更简单一些, 把从s位开始的T子串转化为一个整数, 把P串也转化成一个整数, 只要t[s]=p ,即两个串对应的整数相等, 很明显两个串也就匹配了, 举个例子就懂了;

 

假设字符串里只有a,b,c三个字符, 对应的10进制数为: a:0, b:1, c:2;

 

假设文本串T:abc

假设模式串P: ab

 

那么先将P串转化成整数就是0*10+1=1

文本串T的子串转化成整数分别是: T[0]=0*10+1=1;  T[1]=1*10+2=12;

 

其实就是把每个字符对应一个d进制数的1位, 然后像二进制一样, 求出它对应的整数 ,这里转化有个迭代运算方法,比较方便,叫做霍纳法则,可以查一下,代码里也有体现.

 

现在匹配变成了判断T[s]==p ,那么就匹配成功.

 

但是, 如果串P很长, 那么整数会很大很大, 会溢出, 所以必须做一些处理, 就是MOD运算.

 

两个不同的串对应的整数MOD后也可能相等,这样判断起来就没啥意思了, 但是有一个特性, 如果两个串对应的整数的MOD结果不同,那么这两个串不可能相同!

 

所以, 利用这种方法, 可以在朴素的匹配方法的基础上, 利用这个性质直接排除一些位置的判断 ,这样就减小了复杂度.

 

预处理就是求t[s]与p, 单独求每个t[s] 复杂度就是平方级了, 所以这里有一个巧妙的递推方法求所有的t[s].

 

举个例子, 不讲公式了.

 

假设文本串T:abc

假设模式串P: ab

 

T[0]= ab , 对应01

T[1]= (01 - 0*10) *10 +2 =12

 

就是本来ab对应01 , 把a的0去掉,在1的右边加上c=2, 变成12 ,这个过程是可以利用不同进制间的转化的原理用算式算出来的.

 

 

就讲这些,看算法导论应该可以轻松看懂,很简单.

原创粉丝点击