您的位置:首页 > 运维架构 > 网站架构

KPM算法(附视频网站与代码)

2017-12-17 20:46 302 查看
KPM算法

最主要的内容就是求解:最长公共前后缀数组:

可以参考如下视频讲解:

https://www.youtube.com/watch?v=dgPabAsTFa8&t=623s

很清晰;

仅仅贴出看完视频之后所编写的代码,部分地方有微妙的改动。

其中有关于最长公共前后缀数组的优化:思想就是剔除不必要的移动操作,

比如match字串如果为aaaab,如果比较了第5位知道不相等,可以直接将子串移动到最先开始的位置,因为前4个字母是相等的.

优化部分的代码如下:

#include<iostream>
#include<string>
#include<vector>

//author:L
//done:2017:12/17
//KPM
using namespace std;
void prefix_table(string& pattern,int* prefix,int n);
int key_match(string& src,string& match,int* prefix,int mod);//mod = 0 raw, 1:kpm
int key_match_kpm_find_all(string& src,string& match,int* prefix,int* result);
int main(){
string src;
string match;
int result[50] = {0};
getline(cin,src);
getline(cin,match);
int len = match.size();
int* prefix = new int [len];
prefix_table(match,prefix,len);

cout<<key_match(src,match,prefix,0)<<endl;
cout<<key_match(src,match,prefix,1)<<endl;

len=key_match_kpm_find_all(src,match,prefix,result);
if(len==0){
cout<<"does not exist the same string";
}
else{
cout<<"find it ,the position are:"<<endl;
for(int i=0;i<len;i++){
cout<<result[i]<<" ";
}
}
return 0;
}
void prefix_table(string& pattern,int* prefix,int n){
int len = -1;
int i = 0;
prefix[0] = -1; //忘记了这一步
while(i<n){
if(len ==-1 ||pattern[len]==pattern[i]){
++len;
++i;
prefix[i] = len;
//可以做如下优化
/*
if(prefix[len] == prefix[i]){
prefix[i] = prefix[len];
}
else{
prefix[i] = len;
}
*/
}
else{
len = prefix[len];  //prefix回溯;
}
}
}
int key_match(string& src,string& match,int* prefix,int mod){
int len_src = src.size();
int len_match = match.size();
int i = 0;
int j = 0;
if(len_src<len_match){
return -1;
}
if(mod == 0){
while(i<len_src && j<len_match){
if(j==-1 || src[i] == match[j]){
++i;
++j;
}
else{
j = prefix[j];
}
}
}
else{
while(i<len_src && j<len_match){
if(src[i] == match[j]){
++i;
++j;
}
else{
i = (i-j)+1;////晦朔+1;
j = 0; //忘记的一步;
}
}
}
if(j == len_match){
return i-j;
}
else{
return -1;
}
}
int key_match_kpm_find_all(string& src,string& match,int* prefix,int* result){
int len_src = src.size();
int len_match = match.size();
int i = 0;
int j = 0;
int flag = 0;
if(len_src<len_match){
return 0;
}
while(i<len_src){
if(j==-1 || src[i] == match[j]){
++i;
++j;
}
else{
j = prefix[j];
}
if(j == len_match){
result[flag] = i-j; //记录找到的位置
flag++;
}
}
return flag;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐