解题思路:
哈希表+位操作
一、算法分析
1.模式串编码
编码方式:手动编码和计算编码
A--00
C--01
G--10
T--11
或
A--(A-A+1)%5=1%5=1=01
C--(C-A+1)%5=3%5=3=11
G--(G-A+1)%5=7%5=2=10
T--(T-A+1)%5=20%5=0=00
那么每个模式串就是一个数字组合如
ACGTACGTCT--01111000011110001100
一个int类型有32位,使用其中低20位表示编码
20位0、1串共有2^20种组合。因此,hashTable的大小为2^20=1024*1024
2.字符串的遍历
初始10个字符进行初始编码,然后每右移一个字符,则将编码左移2位,并将第21、22位0置,最低的两位置最新字符的编码
3.时间和空间复杂度
时间复杂度O(n)
空间复杂度O(1)
二、源码实现
#include<iostream>
#include<string>
#include<vector>
using namespace std;
vector<string> findRepeatedDnaSequences(string s){
vector<string> ret;
size_t n=s.size();
if(11>n)return ret;
char hashTable[1024*1024]="";
int hashValue=0;
for(size_t i=0;i<10;++i){
hashValue=hashValue<<2|((s[i]-'A'+1)%5);
}
hashTable[hashValue]=1;
for(size_t i=10;i<n;++i){
hashValue=(hashValue<<2)&(~0x300000)|(s[i]-'A'+1)%5;
if(0==hashTable[hashValue])hashTable[hashValue]=1;
else if(1==hashTable[hashValue]){
hashTable[hashValue]=2;
ret.push_back(s.substr(i-9,10));
}
}
return ret;
}
int main(){
string s="AAAAACCCCCAAAAACCCCCCAAAAAGGGTTT";
vector<string> ret=findRepeatedDnaSequences(s);
for(size_t i=0;i<ret.size();++i){
cout << ret[i] << endl;
}
return 0;
}
参考链接:
http://www.cnblogs.com/hzhesi/p/4285793.html
https://leetcode.com/discuss/29623/11ms-solution-with-unified-hash-fxn