子串匹配算法

摘要:
1子字符串匹配算法T字符串是要匹配的字符串;P是模式字符串;len˃len1.1inti=0;intj=0;而{if{i++;j++;}否则{j=0;i=i-j+2}}如果{returni-j+1;}否则{return-1;}BF算法1.1.1 BF方法的要点[1]工作原理:如果工作下标i和j对应的字符相同,则两个工作下标都将向后移动;相反,j回溯到模式字符串的第一个字符,并且j回溯到匹配循环开始时所指的字符j的下一位[2]:如果j的值等于模式字符串P的长度,则子字符串匹配成功。

1 子串匹配算法

T串为待匹配的字符串;P为模式串;且 len(T)>len(P)

1.1

int i=0;

int j=0;

while(i<len(T)-len(P)+1&&j<len(P))

{

if (T[i]==p[j])

{

i++;

j++;

}

else

{

j=0;

i=i-j+2

}

}

if (j=len(T))

{

return i-j+1;

}

else

{

return -1;

}

BF算法
1.1.1 BF法要点

[1] 工作原理:

如果工作下标i,j对应的字符相同,那么则两个工作下标都向后移;反之j回溯到模式字符串的首字符,j回溯该轮匹配开始时j所指的字符的下一位

[2] 结果:

如果j的值等于模式串P的长度,则子串匹配成功。

[3] 缺陷:

若T串中含有多个P串,则只能找到第一个;当T串中不含有P串作为子串时,无法快速定位到P,T的最大公共子串。

1.2 KMP算法

1.2.1 KMP算法工作原理

[1] 提出KMP算法的由头

避免BF算法中在匹配失败的情况下出现的一些不必要的回溯。具体包括以下两个方面:

1) 指向T串的工作下标在每轮匹配失败后不进行回溯;

2) 指向P串的工作下标在每轮匹配失败后不一定回溯到P串首部。

完成上述两个简化的核心思想:对称前缀串

对称前缀串:和后缀重叠对称

KMP算法

#include <iostream>

#include <vector>

#include <map>

using namespace std;

#pragma once

class kmp

{

public:

kmp(wstring s1,wstring s2);//构造函数为m_traget,m_pattern赋值,长度小的定位为

void KMPMatcher();//执行KMP算法

void ComputePrefixFunction();

//void BestMatchInfo();//根据匹配的模式字符串的前缀串的长度,将匹配信息排序

void GetMatchInfo(vector< pair<int,int>>&matchinfo );

~kmp(void);

private:

wstring m_target;//带匹配的目标字符串

wstring m_pattern;//匹配的模式串

//map<int,int> matchinfo;//保存两个字符串之间的匹配信息

//第一个int 保存目标串的下标,第二个int 是匹配的长度

//vector<pair<int,int>> bestmatch;//目标字符串和模式字符串的最优匹配程度第一个int保存的是目标字符串的结尾位置,第二个字符串是两个串之间匹配上的最大字串

int *prefixInfo;

int *matchInfo;//目标字符串中每个位置所匹配上的模式子串的最末一位下标

};

#include "StdAfx.h"

#include "kmp.h"

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

/* 构造函数,根据长度来确定哪个串是目标串,哪个串是模式串 */

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

kmp::kmp(wstring s1,wstring s2)

{

if (s1.size()>=s2.size())

{

m_pattern=s2;

m_target=s1;

}

else

{

m_pattern=s1;

m_target=s2;

}

int itssize=m_pattern.size()+1;

prefixInfo=new int[itssize];

memset(prefixInfo,-1,itssize*sizeof(int));

itssize=m_target.size()+1;

matchInfo=new int[itssize];

memset(matchInfo,-1,itssize*sizeof(int));

}

kmp::~kmp(void)

{

delete prefixInfo;

delete matchInfo;

}

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

/* 获得模式串中符合要求的前缀的最后一位下标 */

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

void kmp:: ComputePrefixFunction()

{

int m=m_pattern.size()+1;

const wchar_t*P=m_pattern.c_str();

prefixInfo[0]=-1;

int k=-1;

for (int q=1;q<m;q++)

{

while (k>-1 && P[k+1]!=P[q])

{

k=prefixInfo[k];

}

if (P[k+1]==P[q])

{

k++;

}

prefixInfo[q]=k;

}

}

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

/* 执行KMP算法 */

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

void kmp::KMPMatcher()

{

const wchar_t*P=m_pattern.c_str();

const wchar_t*T=m_target.c_str();

int m=wcslen(P)+1;

int n=wcslen(T)+1;

ComputePrefixFunction();

int q=-1;//起始赋值为非法下标

for (int i=0;i<n;i++)

{

while(q>-1&&P[q+1]!=T[i])

{

q=prefixInfo[q];

}

if(P[q+1]==T[i])

{

q++;

if (matchInfo[i]==-1)

{

matchInfo[i]=q;

}

}

if (q==m-1)

{

q=prefixInfo[q];

}

}

}

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

/* */

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

void kmp::GetMatchInfo(vector< pair<int,int>>&matchinfo )

{

for (int i=0;i<=m_target.size();i++)

{

matchinfo.push_back(make_pair(i,matchInfo[i]));

}

}

免责声明:文章转载自《子串匹配算法》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇直流电源防反接措施Android中使用commons-codec-1.6.jar 进行Base64编解码出现的问题下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章