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

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

串的比较:

       计算机中使用的是标准的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<
        
        
          < 
          
        
       
       
      
      
     
     
    
    




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

博士僧小星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值