classSolution{
public List<String>findRepeatedDnaSequences(String s){
int L =10, n = s.length();
HashSet<String> seen =newHashSet(), output =newHashSet();// iterate over all sequences of length Lfor(int start =0; start < n - L +1;++start){
String tmp = s.substring(start, start + L);if(seen.contains(tmp)) output.add(tmp);
seen.add(tmp);}returnnewArrayList<String>(output);}}
次に、スライスAAAAACCCCC-> AAAACCCCCAについて考えます。整数配列で> 0000111110もしハッシュ再計算し、先頭の0を削除し、末尾の0を追加する場合- 0000011111を表す: H 1 =(時間0 ×4 - C 0 4 L)+ CのL + 1。
ウィンドウスライスとハッシュ計算が一定時間で完了することがわかります。
アルゴリズムは次のとおりです。
シーケンスの初期位置からシーケンスをトラバースします:1からN-1。
start == 0の場合、最初のシーケンスs [0:L]のハッシュ値を計算します。
それ以外の場合、回転ハッシュは前のハッシュ値から計算されます。
ハッシュ値がハッシュセットに含まれている場合、重複するシーケンスが検出され、出力が更新されます。
それ以外の場合は、ハッシュ値をハッシュセットに追加するに追加します。
出力リストを返します。
Javaの例は次のとおりです。
classSolution{
public List<String>findRepeatedDnaSequences(String s){
int L =10, n = s.length();if(n <= L)returnnewArrayList();// rolling hash parameters: base aint a =4, aL =(int)Math.pow(a, L);// convert string to array of integers
Map<Character, Integer> toInt =newHashMap(){
{
put('A',0);put('C',1);put('G',2);put('T',3);}};int[] nums =newint[n];for(int i =0; i < n;++i) nums[i]= toInt.get(s.charAt(i));int h =0;
Set<Integer> seen =newHashSet();
Set<String> output =newHashSet();// iterate over all sequences of length Lfor(int start =0; start < n - L +1;++start){
// compute hash of the current sequence in O(1) timeif(start !=0)
h = h * a - nums[start -1]* aL + nums[start + L -1];// compute hash of the first sequence in O(L) timeelsefor(int i =0; i < L;++i) h = h * a + nums[i];// update output and hashset of seen sequencesif(seen.contains(h)) output.add(s.substring(start, start + L));
seen.add(h);}returnnewArrayList<String>(output);}}
classSolution{
public List<String>findRepeatedDnaSequences(String s){
int L =10, n = s.length();if(n <= L)returnnewArrayList();// rolling hash parameters: base aint a =4, aL =(int)Math.pow(a, L);// convert string to array of integers
Map<Character, Integer> toInt =newHashMap(){
{
put('A',0);put('C',1);put('G',2);put('T',3);}};int[] nums =newint[n];for(int i =0; i < n;++i) nums[i]= toInt.get(s.charAt(i));int bitmask =0;
Set<Integer> seen =newHashSet();
Set<String> output =newHashSet();// iterate over all sequences of length Lfor(int start =0; start < n - L +1;++start){
// compute bitmask of the current sequence in O(1) timeif(start !=0){
// left shift to free the last 2 bit
bitmask <<=2;// add a new 2-bits number in the last two bits
bitmask |= nums[start + L -1];// unset first two bits: 2L-bit and (2L + 1)-bit
bitmask &=~(3<<2* L);}// compute hash of the first sequence in O(L) timeelse{
for(int i =0; i < L;++i){
bitmask <<=2;
bitmask |= nums[i];}}// update output and hashset of seen sequencesif(seen.contains(bitmask)) output.add(s.substring(start, start + L));
seen.add(bitmask);}returnnewArrayList<String>(output);}}