Rabin-Karp

Rabin-Karp算法

用途

此算法主要用来解决字串匹配问题,例如设s为一个字符串,s1为一个字串,我们的目的是判断s中是否存在s1,也可以判断有多少s1字串

解决

  1. 对于此问题的解决,可以采用暴力解法,即从s中逐个字串的查找,然后判断是否存在,其优点是不需要对字串进行预处理,缺点是时间复杂度太高O(MN)
  2. 采用Rabin-Karp算法,该算法的主要思想是采用哈希,把字符串计算成一个哈希值,然后判断是否相等

Rabin-Karp算法具体实现

我们假设字符串中只包含小写字符,则进制为26进制,我们设字串中字符的个数为m,则字串的哈希值的计算为:
hash(s1)=s1[0]*dm-1 *+s1[1]dm-2+…+s1[m-1] (其中d为进制数)
同理,对字符串s(设字符的个数为n)也采用此算法进行计算,s能够截取的字串一共有m-n+1个可能。对于每一个字串我们无需重新计算,可以利用上一步的结果进行计算,例如我们设划片的哈希值为hash(s[0]) 表示从0开始截取的字串的哈希值,则hash(s[1])=d
(hash(s[0])-s[0]*dm-1 )+s[n]
此外如果哈希值过大我们也可以采用求模运算缩小哈希值,但带来的缺点是会造成哈希冲突。
具体问题:

所有 DNA 都由一系列缩写为 ‘A’,‘C’,‘G’ 和 ‘T’ 的核苷酸组成,
例如:“ACGAATTCCG”。在研究 DNA 时,识别 DNA 中的重复序列有时会对研究非常有帮助。编写一个函数来找出所有目标子串,目标子串的长度为 10,且在 DNA 字符串 s 中出现次数超过一次

示例 1:
输入:s = “AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT”
输出:[“AAAAACCCCC”,“CCCCCAAAAA”]

问题分析

此问题即字符串匹配问题,我们可以设A=0,C=1,G=2,T=3即四进制的数,然后每取10个字串计算一次哈希值即可

代码实现

class Solution {
public:
    vector<string> findRepeatedDnaSequences(string s) {
        /*unordered_map<string,int> m;
        vector<string> res;
        int size=s.size();
        int start=0;
        string s1;
        while(start<=size-10){
            s1=s.substr(start,10);
            if(m[s1]==1) res.emplace_back(s1);
            m[s1]++;
            start++;
        }
        return res;*/
        //不取余数的情况下不会有冲突 取余数则可能冲突
        int n=s.size(),d=4,m=10;
        vector<string> res;
        map<char,int> f;
        map<int,int> hash; //用来保存哈希值
        f['A']=0; f['C']=1; f['G']=2;f['T']=3;
        int h=0;
        for(int i=0;i<n-m+1;i++){
            h=0;
            for(int j=0;j<m;j++){
                h=h*d+f[s[i+j]];
            }
            if(hash[h]==1){
                res.emplace_back(s.substr(i,m));
            }
            hash[h]++;
        }
        return res;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值