KMP 스트링 매칭 알고리즘 상세

서문 :

어떻게 알고리즘 코드가 배운 것을 기억하지만, 문제를 어떻게 배운다.

알고리즘은 정말 티치 다른 사람에게 배울 수 있습니다.

예를 인용 두 문자열 S 및 T 감안 T Q S 서브 스트링에 속하는 경우.

이것은 기본 문자열 일치 문제, 우리는 쉽게 브 루트 포스 방법을 생각할 수 있습니다.

브 루트 포스 방법 :

설명의 편의와 이해를 위해, 우리는 패턴 문자열의 주요 문자열 문자열 S, T 문자열을 호출합니다.

문자 인 경우 시작하는 주요 캐릭터 열거 패턴 문자열에서 같은 경기를 뒤로 계속 다른 출발점 업데이트하고 경기를 다시 시작하는 것입니다.

포인터 I, J의 정의

내가 : i 번째 주요 문자열 일치 문자

J : 이전이 일치 한 문자열 패턴 J 문자

초기 상태

문자 스트링의 메인 일치한다 [I] = 'A'및 모드 문자열 동일 t [J + 1] = 'A', 일치 성공. 포인터 이동 후, ++; J ++.

마찬가지로, 다음 경기 후,

S 메인 캐릭터가 다음 문자 t [I] = 'B'모드와 문자열 매칭되도록 [J를 + 1] = 'A ' 다른은 일치하지. i가 2 = 시작점 업데이트 열거는 정합 렌 문자 수가 대응되는 문자열 J == (패턴 문자열 길이)까지 패턴까지 다시 시작된다.

기준 시간 복잡도 : O (N * m)

KMP 알고리즘 :

KMP 알고리즘의 특성상 무력 방법을 최적화. 삭제 작업은 재사용 가능한 정보, 유효하지 않습니다.

하자, 프로세스의 시뮬레이션 위에서 설명한 계속

점과 경기를 시작하기 몇 가지 업데이트 후, 우리는 더 많은 국가에 비해 얻을. 절차의 무단 동력 방법에 따라, 순간에 매치가 실패 난 = 5에 따라서 시작점 업데이트 열거부터 = 4.

그러나 실제로 이러한 작업을하지 않아도, 우리는 관찰 :

  设K, 님의 [IK] S ... [I-2]의 [I-1] t = [1] ... T [K-1] T [K] ( S <IK <= I-1 )

  K가 존재하지 않는다면, 어떤 점 D (들 <D <= I-1)의 시작 지점으로의 패턴의 문자열과 일치 할 수 없다.

  K가 존재하는 경우 :

    만약 t [K + 1]! = [I] S는, 이 패턴의 문자열과 일치 할 수 없다.

    若t[k+1]=s[i],则有可能以i-k为起点匹配出模式串。

①:都会因s[i-1]或之前的某个字符失配而断掉。

②:会因s[i]失配而断掉。

图1:不存在满足条件的k,从任意起点p(s<p<=i-1)都因某字符q匹配不到i-1

图2:存在满足条件的k,但t[k+1]!=s[i],因字符i匹配不到i-1

图3:既存在满足条件的k,t[k+1]=s[i],那么则有可能以i-k为起点匹配出模式串

因而,当匹配失败时,只需找到满足条件的k的最大值。若存在,主串向后匹配,以i-k为起点;若不存在,主串也向后匹配,寻找新的起点。

请思考,选择最大的k是否会漏掉可能的匹配起点?(答案见下文)

算法实现:

我们知道:s[s]..s[i-2]s[i-1]=t[1]..t[j-1]t[j]

  因为s<i-k<=i-1,

  所以s[i-k]..s[i-2]s[i-1]=t[j-k+1]..t[j-1]t[j]

因而我们只需要在模式串已匹配部分寻找k即可。

由于通常情况下模式串长度比较小,我们可以初始化出模式串中每个位置的k值。我们常用next[]数组存储模式串中每个位置的k值。

那么如何求得next[i]?

其实我们求得next[i]的过程等价于用模式串匹配自身的过程。为位置i寻找最长前缀后缀,可以想成用i前面的字符串去匹配模式串,到i最多能够匹配多长。这样以来问题就迎刃而解了,我们只需要进行两次匹配,一次求得next数组,一次匹配模式串。

注意:满足条件的k是指由i-k到i-1能够匹配模式串前k个字符,同时s[i+1]=t[k+1]!

算法流程:

1.初始化指针i=1,j=0

2.循环枚举主串待匹配字符i

3.枚举一个字符就对模式串进行一次匹配:

  若s[i]=t[j+1],则模式串第j+1个字符匹配成功,i++;j++

  若s[i]!=t[j+1],匹配失败,则更新j等于最长的满足条件的k,i++

4.当j=len时,匹配成功,跳出循环。

代码如下:

 1 void get_next()
 2 {
 3     int i,j;
 4     j=0;
 5     next[1]=0;
 6     for(i=2;i<=lent;i++){
 7         while(j>0&&t[j+1]!=t[i])j=next[j];
 8         if(t[j+1]==t[i])j++;
 9         next[i]=j;
10     }
11 }
12 
13 void KMP()
14 {
15     int i,j;
16      j=0;
17      for(i=1;i<=lens;i++){
18          while(j>0&&t[j+1]!=s[i])j=next[j];
19          if(t[j+1]==s[i])j++;
20          if(j==lent)ans[++cnt]=i-j+1;
21     }
22 }

 

next数组的求得很关键,这几天要期末考试,学业繁重。日后加图完善!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  

추천

출처www.cnblogs.com/Neat-Foxes/p/12098930.html