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

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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值