字符串匹配的KMP算法

举例来说,有一个字符串”BBC ABCDAB ABCDABCDABDE”,我想知道,里面是否包含另一个字符串”ABCDABD”?
1、字符串”BBC ABCDAB ABCDABCDABDE”的第一个字符与搜索词”ABCDABD”的第一个字符,进行比较。因为B与A不匹配,所以搜索词后移一位。
2、因为B与A不匹配,搜索词再往后移。
3、就这样,直到字符串有一个字符,与搜索词的第一个字符相同为止。
4、接着比较字符串和搜索词的下一个字符,还是相同。
5、直到字符串有一个字符,与搜索词对应的字符不相同为止。
6、这时,最自然的反应是,将搜索词整个后移一位,再从头逐个比较。这样做虽然可行,但是效率很差,因为你要把”搜索位置”移到已经比较过的位置,重比一遍。
7、一个基本事实是,当空格与D不匹配时,你其实知道前面六个字符是”ABCDAB”。KMP算法的想法是,设法利用这个已知信息,不要把”搜索位置”移回已经比较过的位置,继续把它向后移,这样就提高了效率。
8、借助最长公共前缀后缀长度数组,将模式串向左移动合适的位置。
#include <iostream>
#include <string.h>
#include <stdio.h>
using namespace std ;
 
int next[100] ;
 
void getNext( char p[] )     {
    int len = strlen(p) ;
    next[0] = 0 ;
    int i = 0 , j = 0 ;
    for(j = 1 ; j < len ; j++) {                // i 代表最长前缀后缀长度
        while( p[i] != p[j] && i > 0  )          // 当p[i] != p[j] 时,减小最长前缀后缀长度
            i = next[i-1] ;
        if(p[i] == p[j])    {
            i++ ;                               //最长公共前缀后缀长度+1
            next[j] = i ;                       //匹配失败时跳到该处
        }
        else
            next[j] = 0 ;
    }
}
int main()  {
    char p[100] ;
    cin >> p ;
    int lenp = strlen(p) ;
    getNext(p);
    char s[1000] ;
    getchar() ;
    gets(s) ;
    int lens = strlen(s) ;
    int j = 0 ;
    bool flag = false ;
    for(int i = 0 ; i < lens ; i++)     {
        if(p[j] == s[i])
            j++ ;
        else if(j-1 >= 0)
            j = next[j-1] ;
        if(j == lenp)   {
            flag = true ;
            j = i ;
            break ;
        }
    }
    cout <<"结束位置:"<< j+1 << endl ;
    if(flag)
        cout << "YES" << endl ;
    else
        cout << "NO" << endl ;
    return 0 ;
}

 


posted @ 2014-10-23 09:52  NYNU_ACM  阅读(380)  评论(0编辑  收藏  举报