hiho第三周——字符串匹配KMP算法

来源:互联网 发布:软件 po 编辑:程序博客网 时间:2024/06/06 00:19

hiho第三周——字符串匹配KMP算法

题目链接:http://hihocoder.com/problemset/problem/1015
资料来源于网络:http://kb.cnblogs.com/page/176818/

注意点

1、KMP算法的核心思想是next数组,保留匹配的信息,减少计算量

2、我这里主要应用start标记字符串s中用于模板pattern匹配的第一个字符的位置,match_num表示当前s中以start开始的字符串与模板pattern匹配的字符个数

3、next数组的信息要尽量用上,每当不匹配出现时,start和match_num都要更新。start要向后移动match_num-next[match_num];match_num要更新为next[match_num];
这样下一次匹配将从s[start+match_num]开始。所以时间复杂度就是遍历一遍字符串s

4、更新match_num = next[match_num]时,注意边界条件,match_num=0时的情况

5、next数组只需要计算一遍,不要放到遍历s字符串的循环中

6、next数组可以在前面加一个0节点用于简化代码

7、动态数组 int * next = new int[val];

可执行代码

#include<iostream>#include<fstream>#include<string>using namespace std;//计算next数组,这是KMP算法的核心int * calculate_next(string pattern){    int *next = new int[pattern.size()+1];    //注意边界条件,加一个next[0]简化代码    next[0] = -1;    if(pattern.size()<1)        return next;    next[1] = 0;    for(int i = 2;i <= pattern.size(); i++)    {        if(pattern[next[i-1]]==pattern[i-1])            next[i] = next[i-1]+1;        else        {            if(pattern[0]==pattern[i-1])                next[i] = 1;            else                next[i] = 0;        }    }    return next;}//返回在原串中出现的次数int KMP(string s,string pattern){    int result = 0;//pattern在原串中出现的次数    int start = 0;//标记s用于与pattern匹配的开始位置    int match_num = 0;//记录已经匹配的字符数    int s_length = s.size();    int p_length = pattern.size();    //计算next数组    int *next;    next = calculate_next(pattern);    for(int i = 2;i <= pattern.size(); i++)    {        next[1] = 0;        if(pattern[next[i-1]]==pattern[i-1])            next[i] = next[i-1]+1;        else        {            if(pattern[0]==pattern[i-1])                next[i] = 1;            else                next[i] = 0;        }    }    while(start+match_num<s_length)    {        if(s[start+match_num]==pattern[match_num])        {            match_num++;            //next数组只需要算一遍,不要在这计算            //next[match_num] = next[match_num-1] + 1;        }        else        {            start += (match_num-next[match_num]);            //充分利用next数组中的信息,除了start利用上,match_num也要用上(花了很久去优化计算next数组的方法,结果是这里耗时了)            //match_num = 0;            match_num = max(0,next[match_num]);        }        if(match_num==p_length)            result++;    }    free(next);    return result;}int main(){    ifstream cin("input.txt");    string str;    string pattern;    int N;    cin>>N;    getline(cin,pattern);    while(N--)    {        getline(cin,pattern);        getline(cin,str);        cout<<KMP(str,pattern)<<endl;    }    return 0;}
0 0
原创粉丝点击