首页 > 编程语言 > 详细

串和字符串查找算法

时间:2021-05-14 21:07:15      阅读:18      评论:0      收藏:0      [点我收藏+]

串:

主要讲字符串,面试和笔试全部内容都在字符串上:
字符串操作:字符串拷贝(strcpy) 字符串连接(strcat) 字符串比较(strcmp)
字符串获取长度(strlen) 等等都在C语言字符串那一章节讲过了,也写了。
 

主要讲字符串查找:

第一种正确算法:

技术分享图片

 

 

下面两种算法是正确的:

第二种算法:普通(朴素)查找

技术分享图片

BF算法有哪些缺点:

                                  优点:容易理解,代码容易实现

                                  缺点:时间复杂度太大了,是O(n*m)
 
那么为什么还要有KMP算法:i不回退,打死都不回退
KMP算法,极端情况下,时间复杂度为O(n+m)
K M P是发现这个算法的三个外国数据家的名字首字母
 

两个难点:

技术分享图片

 

 技术分享图片

 

 技术分享图片

 

 

总结:第一种情况下:i回退没有价值,所以不回退
           第二种情况下:i回退虽然有价值,但是i回退这个操作可以让j替代,以避免让i回退
 
第二个问题:j回退到哪里?
                     说是回退到适当的位置k,那么k怎么求?
技术分享图片

 

 技术分享图片

 

 

//next数组保存是,失配后,返回前面字符串的最大相似度的地方 
static int *Get_next(const char *sub) 
{ 
      int len = strlen(sub); 
      int *next = (int *)malloc(sizeof(int) * len); 

      next[0] = -1; 
      next[1] = 0; 

      int j = 1; 
      int k = 0; 
      while(j+1 < len)//j+1是通过已知求未知的未知位置,求的这个未知位置得合法,在数组长 度内就合法 
      { 
           if((k==-1) ||sub[j] == sub[k]) 
           { 
                 next[++j] = ++k; 
                 /*k++;
                    j++; 
                    next[j] = k;*/ 
           }
          else 
           { 
                 k = next[k];
            } 
        }
        return next; 
}

//KMP算法,特点:i打死不回退,时间复杂度O(n+m) 
int KMP_Search(const char* str, const char *sub, int pos) 
{ 
        //断言 防止指针为NULL 并且防止pos位置非法 
        if(str == NULL || sub == NULL || pos < 0 || pos >= strlen(str)) return -1; 

        int lenstr = strlen(str);//获取主串长度 
        int lensub = strlen(sub);//获取子串长度 

        int i = pos;//i代表主串的判断位置 得从pos开始判断 
        int j = 0;// j代表子串的判断位置 

        int *next = Get_next(sub); 
        while(i<lenstr && j<lensub)//如果主串和子串都没走到头,就继续进行 
        { 
              if((j == -1) || str[i] == sub[j])//两者相等,则同时向后走 
              { 
                    i++; 
                    j++; 
               }
              else//不相等,根据回退规则,进行回退即可 
              { 
                    //i = i-j+1;//i打死不回退 
                    //j = 0; j回到到next[j]里面 
                    j = next[j]; 
               } 
          }

          free(next); 
          //while退出,有两种情况,1.没找到 2.找到了 
          if(j >= lensub)//如果子串走到头,则判断找到了 
          { 
                return i-j; 
          }
          return -1; 
      }


//朴素(BF)查找算法 特点:1.相等,同时向后走 2.如果不相等,j回退到0,而i回退的i-j+1 
// 3.如果j走除了范围,证明找到了,返回值为i-j 
//面试笔试必考,不会也得背过 
int BF_Search(const char* str, const char *sub, int pos) 
{ 
       //断言 防止指针为NULL 并且防止pos位置非法 
       if(str == NULL || sub == NULL || pos < 0 || pos >= strlen(str)) return -1; 

       int lenstr = strlen(str);//获取主串长度 
       int lensub = strlen(sub);//获取子串长度 

       int i = pos;//i代表主串的判断位置 得从pos开始判断 
       int j = 0;// j代表子串的判断位置 

       while(i<lenstr && j<lensub)//如果主串和子串都没走到头,就继续进行 
       { 
              if(str[i] == sub[j])//两者相等,则同时向后走 
              { 
                     i++;
                     j++; 
              }
              else//不相等,根据回退规则,进行回退即可 
              { 
                     i = i-j+1; 
                     j = 0; 
               } 
        }
        //while退出,有两种情况,1.没找到 2.找到了 
        if(j >= lensub)//如果子串走到头,则判断找到了 
        { 
               return i-j; 
         }
         return -1; 
}

int main() 
{ 
         const char *a = "ababcabcdabcde"; 
         const char *b = "abcd"; 
         int tmp = KMP_Search(a, b, 6); 
         printf("%d\n", tmp); 
         return 0; 
}

 

串和字符串查找算法

原文:https://www.cnblogs.com/xpei-1124/p/14769632.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!