寻找字符字串的两个方法

来源:互联网 发布:淘宝智能版怎么装修 编辑:程序博客网 时间:2024/06/05 17:55

寻找字符子串的两个方法

提供两个字符串 A 和 B,求 B 在 A 中出现的次数和位置。

直接暴力匹配时间复杂度太高,效率太低,时间一定会超时。

两个方法

KMP 算法,时间复杂度O(m + n);

源码:

//优化过后的next数组求法,核心部分void GetNextval(char* p, int next[])  {      int pLen = strlen(p);      next[0] = -1;      int k = -1;      int j = 0;      while (j < pLen - 1)      {          //p[k]表示前缀,p[j]表示后缀            if (k == -1 || p[j] == p[k])          {              ++j;              ++k;              //较之前next数组求法,改动在下面4行              if (p[j] != p[k])                  next[j] = k;   //之前只有这一行              else                  //因为不能出现p[j] = p[ next[j ]],所以当出现时需要继续递归,k = next[k] = next[next[k]]                  next[j] = next[k];          }          else          {              k = next[k];          }      }  }  //KMP 算法int KmpSearch(char* s, char* p)  {      int i = 0;      int j = 0;      int sLen = strlen(s);      int pLen = strlen(p);      while (i < sLen && j < pLen)      {          //①如果j = -1,或者当前字符匹配成功(即S[i] == P[j]),都令i++,j++              if (j == -1 || s[i] == p[j])          {              i++;              j++;          }          else          {              //②如果j != -1,且当前字符匹配失败(即S[i] != P[j]),则令 i 不变,j = next[j]                  //next[j]即为j所对应的next值                    j = next[j];          }      }      if (j == pLen)          return i - j;      else          return -1;  }  

哈希算法,时间复杂度度O(m+n)

源码

#define rint register int #define ULL unsigned long longconst ULL seed = 131;inline int strlen(const char* src){    rint len = 0;    while(src[len]) len++;    return len;}RESULT search(const char* src, const char* substr){    RESULT res;    res.count = 0;    int srcLen = strlen(src);    int subLen = strlen(substr);    ULL sum = 1;    for(rint i = 0; i < subLen; i++)    {        sum *= seed;    }    ULL strHash = 0;    ULL subHash = 0;    //核心部分    for(rint i = 0; i < subLen; i++)    {        strHash = strHash * seed + src[i];        subHash = subHash * seed + substr[i];    }    for(rint i = 0; i + subLen < srcLen; i++)    {        if(strHash == subHash)        {            res.indexes[res.count++] = i;        }        if(i + subLen < srcLen)            strHash = strHash * seed + src[i + subLen] - src[i] * sum;    }    return res;}

哈希函数原型:
unsigned int BkdrHash(const char* str, unsigned int len){    unsigned int seed = 131; /*31 131 1313 13131 131313 etc*/    unsigned int hash = 0;    for(int i = 0; i < len; ++i){        hash = (hash * seed) + (*str++);    }    return hash;}




阅读全文
0 0
原创粉丝点击