思路:滑动窗口 + 位运算
- 滑动窗口的关键在于,利用旧序列和新序列的相似性降低运算的复杂度
 - 此题中只有4个字母,那么可以使用2位
bit来记录每一个字母 - 滑动窗口一入一出,更新记录当前的10个字母的整数
res_bit - 如何把右边的读进来?1.左移两位 
res_bit <<= 2   2.把右边的读进来 res_bit |= to_bin[ch] - 如何把左边的弹出去?希望最左边的两位(左数第21 22两位)变成0,也就是希望 & 0111111… 其中,0处在第20位上,
x & ((1 << 20) - 1) - 哈希表里面的key就是位运算的结果x, value就是出现的次数
 - 如何返回需要的字符串呢?需要边读边更新哈希表,如果出现的次数 >= 2,说明应该返回此时的位置了
代码:
 
class Solution:    def __init__(self):         self.L = 10        self.to_bin = {'A': 0, 'C': 1, 'G': 2, 'T': 3}    def findRepeatedDnaSequences(self, s: str) -> List[str]:        '''        位运算:        * 每个数字用两位的二进制字符来表示        * 如何把右边的读进来?1.左移两位 x <<= 2   2.把右边的读进来 x |= to_bin[ch]        * 如何把左边的弹出去?希望最左边的两位(左数第21 22两位)变成0,也就是希望 & 0111111... 其中,0处在第20位上            即 x & ((1 << 20) - 1)        滑动窗口 + 哈希表:        * 哈希表里面的key就是位运算的结果x, value就是出现的次数        * 如何返回需要的字符串呢?需要边读边更新哈希表,如果出现的次数 >= 2,说明应该返回此时的位置了        '''        len_s = len(s)        # 读掉边缘情况        if len_s <= 10:            return []        cnt_str = collections.defaultdict(int)        list_str = list()        # 创建第一个滑动窗口        bit_res = 0        for i in range(self.L):            bit_res = (bit_res << 2) | self.to_bin[s[i]]        cnt_str[bit_res] += 1        # 滚动更新哈希表和滑动窗口        for i in range(self.L, len_s):            # 右边的移动进来            bit_res = ((bit_res << 2) | self.to_bin[s[i]])            # 左边的移动出去            bit_res = (bit_res & ((1 << (2 * self.L)) - 1))            # 更新哈希表            cnt_str[bit_res] += 1            # 如果次数 >= 2            if cnt_str[bit_res] == 2:                list_str.append(s[i - self.L + 1: i + 1])        return list_str