寻找字符字串的两个方法

寻找字符子串的两个方法

提供两个字符串 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 long

const 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值