給定 DNA 字符串(僅含 A, C, G, T),找出所有長度為 10 的重複子串。字符串長度可達 10^5,直接用 HashMap 存儲子串會超出內存限制。
DNA 只有 4 種字符,可用 2 bits 編碼:A=00, C=01, G=10, T=11。長度 10 的子串僅需 20 bits,完美放入 32 位整數。
public ListfindRepeatedDnaSequences(String s) { List res = new ArrayList<>(); if (s == null || s.length() < 11) return res; int hash = 0; Map map = new HashMap<>(); map.put('A', 0); map.put('C', 1); map.put('G', 2); map.put('T', 3); Set seen = new HashSet<>(); Set added = new HashSet<>(); for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); if (i < 9) { hash = (hash << 2) | map.get(c); } else { hash = (hash << 2) | map.get(c); hash &= (1 << 20) - 1; // 保留低 20 位 if (seen.contains(hash) && !added.contains(hash)) { res.add(s.substring(i - 9, i + 1)); added.add(hash); } else { seen.add(hash); } } } return res; }
此技巧適用於所有小字符集、固定長度子串查重問題,如基因序列分析、文本指紋檢測、滾動哈希(Rabin-Karp)算法的核心思想。