字符串的模式匹配算法--KMP算法

        KMP算法是一种高效的模式匹配算法,其最大的特点是指示主串的指针不需要回溯,整个匹配过程中,对主串仅需要从头到尾扫描一遍,这对处理从外设输入的庞大文件很有效,可以边读入边匹配,而无需回头重读,圈复杂度可达到O(n+m)。

        该算法需要对模式串进行预处理,用next[j]表示当前模式中第j个字符与主串中相应字符失配时,在模式串中需要重新和主串中该字符进行比较的字符的位置。其中“-1”表示直接与主串下一个字符比较。

        以一个例子来说明。譬如给的模式串是“abcdaabcac”,经过KMP算法,可得到的next值如下表所示:

下标j
0123456789
模式串
abcdaabcac
next[j]
-1000-110031

附:

  使用KMP算法查找模式串P在源串S中的位置:

/*****************************************************/
class IndexKMP
{
private:
    int* next;  //比较字符的位置,下标从0开始
    char* match;//要匹配的串,下标从0开始
    int length; //要匹配的串的长度

    void IniNext(); //模式串的预处理

public:
    IndexKMP(char* P); //初始化,P为模式串
    ~IndexKMP();

    int Index(char* S, int pos);  //在S中查找模式串P的位置,pos为开始位置
void printNext();
};

/*****************************************************/

/*****************************************************/

#include <string.h>
#include <stdio.h>

IndexKMP::IndexKMP(char* P){
length = strlen(P);
match = new char[length];

//复制
for(int i = 0; i < length; i++)
{
match[i] = P[i];
}
next = new int[length];
IniNext();
}

IndexKMP::~IndexKMP()
{
delete[] match;
delete[] next;
}

//模式串的预处理

void IndexKMP::IniNext()
{
    //求模式串match的next函数修正值并存入数组next。

    //思路:1、从第二个字符开始与第一个字符及之后的字符进行比较,直到找到不同的字符。

    //2、之后,再从该字符开始与不一致字符next值指示的字符(不一定是第一个字符)及之后的字符进行下一轮比较,依此循环。

int i = 0, j = -1, len = length - 1;
next[0] = -1;
while(i < len){
        if(j == -1 || match[i] == match[j]){
            ++i; ++j;
            if(match[i] != match[j])  //对比不等,next值为不相等字符所在的位置
                next[i] = j;
            else next[i] = next[j];  //对比相等,则next值也相等
        }
        else j = next[j]; //重新开始下一轮的对比
    }
}


//成功找到返回从0开始的整数,失败返回-1
int IndexKMP::Index(char* S, int pos)
{
    //利用模式串match的next函数求match在主串S中第pos个字符之后的位置的KMP算法。
    //其中,match非空,0<=pos<GetLength(S)。
   if (pos < 0) pos = 0;

    int i = pos, j = 0, len = strlen(S);
    while(i < len && j < length){
    if( j == -1 || S[i] == match[j])
    {
    ++i; ++j;  //继续比较后继字符
    }
    else j=next[j];  //模式串向右移动
    }

    return (j >= length) ? i-length : -1;
}


void IndexKMP::printNext()
{
for (int i = 0; i < length ; i++)
{
printf("the index of %d is %d.\n", i+1 , next[i]);
}
}

/*****************************************************/

/********************测试****************************/

void main()
{
IndexKMP test("abcdaabcac");
test.printNext();
int pos = test.Index("a12aaabaabcacwqabcdaabcacbgfrg", 0);
printf("%d\n", pos);
}

/*****************************************************/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值