您的位置:首页 > 其它

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

2015-06-11 15:12 323 查看

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: