您的位置:首页 > 理论基础 > 数据结构算法

数据结构_串_串的模式匹配_KMP/BF

2017-01-01 20:24 281 查看
        串是由零个或者多个字符组成的有序序列,又名叫字符串。在串中涉及到一下几个概念:串的长度、空串、子串、以及串的比较和串的模式匹配。

串的比较:

       计算机中使用的是标准的ASCII编码,是由7位二进制数表示一个字符,总共可表示2^7=128个字符,后来由于特殊符号的出现,扩展成8位二进制数表示一个字符,共表示2^8=256个字符。再后来由于世界上的语种非常的多,就产生了Unicode编码,用16位二进制数表示一个字符,总共可表示2^16=6.5万多个字符。当然,Unicode编码的前256个字符和ASCII码完全相同。而字符串的比较则是逐位按照ASCII码的大小进行比较,那么软件中查取相应单词的过程就是这样产生的。

串的模式匹配:

普通的模式匹配算法:

#include
#include
#include
using namespace std;

int BF(const char *des, const char *src, int pos)//返回下标
{
if (des == nullptr || src == nullptr)
{
return -1;
}
int lend = strlen(des);
int lens = strlen(src);
if (pos < 0 || p >= lend)
{
return -1;
}
//while循环进行查找
int i = pos;
int j = 0;
while (i < lend && j < lens)
{
if (des[i] == src[j])
{
++i;
++j;
}
else
{
i = i-j+1;
j = 0;
}
}
if (j >= lens)
{
return i-j;
}
return -1;
}

int main()
{

return 0;
}

KMP算法模式匹配: 对于普通的模式匹配算法而言,当des = "abcdefgoogle"和src = "google"的时候,时间复杂度
                 为O(n+m);而当des = "000000000000000001"和src = "00001"的时候,时间复杂度则变成了O((n-
                 m+1)*m),时间复杂度很高。而这其中产生时间消耗的主要是重复的比较造成的。我们假设i为des
                 的下标,j为src的下标,KMP算法的核心就是i不回溯(不回退),而j根据子串中是否有重复的问题
                 进行选择性回退,j的回退与主串无任何关系。那么j到底回退到什么位置合适,则由next数组和
                 nextval数组确定。
   【next数组】
       next数组的计算相当的简单,不同的教材上方法可能有些许差异,即:next[0] = 0 或者 next[0] = -1;

       例:char arr[] = "a  b  a  b  a  a  a  b  a";

               int next[] = {0, 1, 1, 2, 3, 4, 2, 2, 3};

     
【nextval数组】

      nextval数组是next数组的一个改进版本。需要注意的是当next[0] = 0时,next数组的值是表示的第几个元素,当

      next[0] = -1的时候,表示的是当前下标为next数组值得元素。

       例:      char arr[] = "a  b  a  b  a  a  a  b  a";

        int nextval[] = {0, 1, 0, 1, 0, 4, 2, 1, 0};

KMP算法next版本实现:

#include
#include
#include
#include
#include
using namespace std;

void findNext(const char *src, int *next)
{
//入口检查
if (src == nullptr || next == nullptr)
{
return ;
}
int i = 1;//表示当前要求next数组元素的下标
int j = 0;//表示next的数组元素
next[0] = -1;
next[1] = 0;
int lens = strlen(src);
while (i < lens)
{
//此处的j == 0保证不会出现 j==-1的情况
if (j==0 || src[i] == src[j])
{
++i;
++j;
next[i] = j;
}
else
{
j = next[j];
}
}
}

int KMP(const char *des, const char *src, int pos)
{
if (des == nullptr || src == nullptr)
{
return -1;
}
int lend = strlen(des);
int lens = strlen(src);
int i = pos;
int j = 0;
//动态创建next数组
int *next = new int[100];
findNext(src, next);

while (i < lend && j < lens)
{
if (j==-1 || des[i] == src[j])
{
++i;
++j;
}
else
{
j = next[j];
}
}
delete []next;
if (j > lens)
{
return i-lens;
}
else
{
return -1;
}
}

int main()
{
char *des = "abcdefgoogle";
//char *src = "ef";
//char *src = "le";
//char *src = "";
//char *src = nullptr;
char *src = " ";
int pos = KMP(des, src, 2);
cout<


KMP算法nextval版本实现:

#include
#include
#include
#include

void findNextVal(const char *src, int *nextval)
{
if (src == nullptr || nextval == nullptr)
{
return ;
}
int lens = strlen(src);
if (lens == 0)
{
return ;
}
nextval[0] = -1;
nextval[1] = 0;
int i = 1;
int j = 0;
while (i < lens)
{
if (j == 0 || src[i] == src[j])
{
++i;
++j;
if (src[i] != src[j])
{
nextval[i] = j;
}
else
{
nextval[i] = nextval[j];
}
}
else
{
j = nextval[j];
}
}
}

int KMP(const char *des, const char *src, int pos)
{
if (des == nullptr || src == nullptr)
{
return -1;
}
int lend = strlen(des);
int lens = strlen(src);
if (pos < 0 || pos >= lend)
{
return -1;
}
int i = pos;
int j = 0;
int nextval[100];
findNextVal(src, nextval);

while (i < lend && j < lens)
{
if (j == 0 || des[i] == src[j])
{
++i;
++j;
}
else
{
j = nextval[j];
}
}
if (j >= lens)
{
return i-j;
}
else
{
return -1;
}
}

int main()
{
char *des = "abcdefgoogle";
//char *src = "ef";
//char *src = "le";
//char *src = "";
//char *src = nullptr;
char *src = " ";
int pos = KMP(des, src, 2);
cout<
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息