题目:Repeated DNA Sequences

给定包含A、C、G、T四个字符的字符串找出其中十个字符的重复子串。

思路:

首先,string中只有ACGT四个字符,因此可以将string看成是1,3,7,20这三个数字的组合串;

并且可以发现{ACGT}%5={1,3,2,0};于是可以用两个位就能表示上面的四个字符;

同时,一个子序列有10个字符,一共需要20bit,即int型数据类型就能表示一个子序列;

这样可以使用计数排序的思想来统计重复子序列;

这个思路时间复杂度只有O(n),但是空间复杂度2^20byte辅助空间;

vector<string> LeetCode::findRepeatedDnaSequences(string s){
    vector<string> ret;
    if (s.size() < 11)return ret;
    char count[1048576] = {0};//0x000fffff = 1048575
    int index = 0;
    for (size_t i = 0; i < 9; ++i){//先求第一个子序列
        int value = s[i] - 'A' + 1;//char转成int
        value %= 5;//对5求余,转成2bit的大小
        index = index << 2 | value;//合并成一个值
    }
    for (size_t i = 9; i < s.size(); ++i){
        int value = s[i] - 'A' + 1;//char转成int
        value %= 5;//对5求余,转成2bit的大小
        index = index << 2 | value;//合并成一个值
        index = index & 0x000fffff;//清除前面移位的高位无效数字
        ++count[index];
        if (count[index] < 0)count[index] = 3;
        if (count[index] == 2){//防止重复加入
            ret.push_back(s.substr(i - 9, 10));
        }
    }
    return ret;
}