-
——>BF算法 点我·
BF算法时间复杂度比较高,下面介绍一种改进的模式匹配算法。KMP算法,可以在O(n+m)的时间数量级上完成串的模式匹配操作,每当匹配失败时,i 不用回溯,而是利用已经得到的“部分匹配”的结果将 j 向左移动一段距离,继续比较 S[i]==T[j] -
在BF算法中:
-
一趟
i=6
a b a b c a b c a c b a b
j=4
a b c a c
- 二趟
我们发现当 i=6,j=4 字符比较不相等时,又需要从 i=3,j=0 重新比较。仔细看看之后,i=3,j=0 和 i=4,j=0 和 i=5,j=0 的比较完全是不需要进行的。因为主串中的 i=3,4,5 的字符必然是 bca ,因为模式串的第一个字符为 a 不必在进行比较了,所以 i 不需要进行回溯,仅需将 j 向左移动到 j=1
i=6
a b a b c a b c a c b a b
j=1
a b c a c
这里有一个问题,**当失配时,模式串的 j 需要向左移动多远?
假设移动到模式串的第k个字符:
则主串 i 之前的 k 个字符 应与模式串 1 到 k 之前的字符相同
Si-k Si-k+1 Si-k+2 Si-1 = T0T1T2…Tk-1
部分匹配结果:
Si-k Si-k+1 Si-k+2 Si-1 = Ti-k Ti-k+1 Ti-k+2 Ti-1
得出:
T0T1T2…Tk-1 = Ti-k Ti-k+1 Ti-k+2 Ti-1
令 next[j] =k;求字符串前缀与后缀相等的最长长度
| 模式串 | a | b | a | b | a | b | c | a |
|---|---|---|---|---|---|---|---|---|
| j | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| next[j] | -1 | 0 | 0 | 1 | 2 | 3 | 4 | 0 |
为了方便 一般把 next[0]=-1
j=1 b字符前就一个字符a 没有后缀也没有前缀字符 next[1]=0
j=2 a字符前有字符ab ab前缀字符有a,后缀字符与b,a与b不相等 next[1]=0
j=3 b字符前有aba,aba前缀字符有a,ab,后缀有a,ba,a=a,最长长度为1,next[3]=1
j=4 字符abab前缀有a,ab,aba,后缀有bab,ab,最长长度为2,ab=ab,next[4]=2
代码实现:
public int IndexOfKMP(String S,String T,int pos){
char []a = S.toCharArray();
char []b = T.toCharArray();
int i=0;int j=0;
while(i<S.length() && j<T.length()){
if(j==-1 || a[i]==b[j]){ // 继续比较 必须j==-1在前面
i++;j++;
}
else{ //j后退重新匹配,i不变
j=next[j];
}
}
if(j>=T.length()) //匹配成功
return i-j;
else //匹配失败
return 0;
}
求next[j]代码:
public void getNext(String T,int [] next){
char []b = T.toCharArray();
next[0]=-1;
int i=0,j=-1;
while(i < T.length()-1)
{
if(j==-1 || b[i]==b[j]){
++i;++j;
next[i]=j;
}
else
j=next[j];
}
}
完整实现:
public class Test {
static int []next = new int[100];
public static void main(String [] args) {
String S = "我是大明我我是小明嘿嘿嘿";
String T = "我是小明";
getNext(T,next);
System.out.println(IndexOfKMP(S,T,0));
}
public static int IndexOfKMP(String S,String T,int pos){
char []a = S.toCharArray();
char []b = T.toCharArray();
int i=0;int j=0;
while(i<S.length() && j<T.length()){
if(j==-1 || a[i]==b[j]){ // 继续比较
i++;j++;
}
else{ //j后退重新匹配,i不变
j=next[j];
}
}
if(j>=T.length()) //匹配成功
return i-j;
else //匹配失败
return 0;
}
public static void getNext(String T,int [] next){
char []b = T.toCharArray();
next[0]=-1;
int i=0,j=-1;
while(i < T.length()-1)
{
if(j==-1 || b[i]==b[j]){
++i;++j;
next[i]=j;
}
else
j=next[j];
}
}
}

- ——>BF算法 点我·
本文介绍了KMP算法,一种比BF算法更高效的模式匹配算法。在BF算法中,当匹配失败时,KMP算法利用部分匹配结果避免回溯,直接将模式串j向左移动。文章详细解释了KMP算法的原理,并给出了计算next数组的步骤,以确定模式串在失配时应移动的距离。最后,展示了KMP算法的代码实现。

1033

被折叠的 条评论
为什么被折叠?



