LeetCode 187. 重复的DNA序列
DNA
序列由一系列核苷酸组成,缩写为 'A'
, 'C'
, 'G'
和 'T'
.。
例如,"ACGAATTCCG"
是一个DNA
序列 。
在研究 DNA
时,识别 DNA
中的重复序列非常有用。
给定一个表示 DNA
序列 的字符串 s
,返回所有在 DNA
分子中出现不止一次的 长度为 10 的序列(子字符串)。你可以按 任意顺序 返回答案。
示例 1:
输入:s = "AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT"
输出:["AAAAACCCCC","CCCCCAAAAA"]
method
维护一个长度为10的滑动窗口,如果窗口内的子串已经出现一次,就把该子串加入到结果中
vector<string> findRepeatedDnaSequences(string s) {
int n = s.size();
vector<string> res;
unordered_map<string, int> hash;
for (int i = 0; i + 10 <= n; i++) {
string str = s.substr(i, 10);
if (++hash[str] == 2) { // 防止重复添加
res.push_back(str);
}
}
return res;
}
也可以用字符串哈希
子串s[i:j]
的哈希值可以通过h[j]-h[i-1]*p[j-i+1]
求得,运用了前缀和的思想
因为这里子串长度是固定的,所以$power=prime^{10}$固定了,就不用hash
数组和power
数组了
const int prime = 31;
vector<string> findRepeatedDnaSequences(string s) {
unsigned long long hash = 0;
unsigned long long power = 1;
for (int i = 0; i < 10; i++) {
hash = hash * prime + (s[i] - 'a');
power *= prime;
}
vector<string> res;
unordered_map<unsigned long long, int> exits;
exits[hash] = 1;
for (int i = 10; i < s.size(); i++) {
hash = hash * prime - power * (s[i - 10] - 'a') + (s[i] - 'a');
if (++exits[hash] == 2) res.push_back(s.substr(i - 10 + 1, 10));
}
return res;
}