DNA
思路一:
这题需要桶+哈希(简化版像A 1 B 2 ......)
具体:
先把数据输入
再枚举可能的右端点,再由右端点得到左端点(l和r相差k)
在 l到r 区间内将这一段区间哈希成一个4进制数后(A 0 C 1 G 2 T 3)(装成函数),将其放入桶中。
最后在枚举所有可能的区间,取他们出现次数的max 值并输出这个值
转换函数:
先开一个ans记录答案,再把l到r区间内的字符遍历一遍,如果是’a‘ t=0其他的类同(t用来记录这个位置上的Hash值),最后ans=ans*4+t(先给t腾个位置再把它放进去,又因为是4进制所以乘4,其效果与10进制下乘10相同),最后,返回ans
思路二:
题目即统计每种连续 k 个碱基的出现次数。
发现 k 很小,并且每一位状态只有 4 种,所以本质不同的串最多有 4 k 个,于
是我们可以用 4 进制数表示。注意到 4 10 = 220,因此可以直接将这些状态出现的
次数存起来。
这里计算一个串的 Hash 值有两种方法,第一种是每个串都重新计算一遍,时
间复杂度为 O(nk),第二种是利用位运算将无用状态取出,并加入新状态,时间
复杂度为 O(n)。这两个复杂度的代码均可。
思路一程序:
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=(1<<20)+1; 4 string s; 5 int buk[N]={0}; 6 int k; 7 int translate(int l,int r)//A 0 C 1 G 2 T 3 四进制 8 { 9 //s[l]~s[r] 10 int ans=0; 11 for(int i=l;i<=r;i++) 12 { 13 int t=0; 14 if(s[i]=='A') t=0; 15 else if(s[i]=='C') t=1; 16 else if(s[i]=='G') t=2; 17 else if(s[i]=='T') t=3; 18 ans=ans*4+t; 19 } 20 return ans; 21 } 22 int main() 23 { 24 getline(cin,s); 25 cin>>k; 26 for(int r=k-1;r<s.length();++r) 27 { 28 int l=r-k+1; 29 int t=translate(l,r); 30 buk[t]++; 31 // cout<<t<<" "; 32 } 33 34 int rans=0; 35 for(int l=0;l<=s.length()-k;l++) 36 { 37 int r=l+k-1; 38 // if(buk[translate(l,r)]>rans) rans=buk[translate(l,r)]; 39 rans=max(rans,buk[translate(l,r)]); 40 } 41 cout<<rans; 42 // cout<<buk[00000]; 43 return 0; 44 }
思路二代码:
1 #include <cstdio> 2 #include <cstring> 3 4 const int MAXN = 5000000; 5 const int MAXR = 1 << 20; 6 7 char a[MAXN + 5]; 8 int n, m, k, cnt[MAXR + 5], f[26], h, ans; 9 int DNA[MAXN + 5]; 10 11 int main() 12 { 13 freopen("dna.in", "r", stdin); 14 freopen("dna.out", "w", stdout); 15 16 f['G' - 'A'] = 1; f['C' - 'A'] = 2; f['T' - 'A'] = 3; 17 18 scanf("%s", a); 19 n = strlen(a); 20 scanf("%d", &k); 21 22 for (int i = 0; i < n; i++) 23 DNA[i] = f[a[i] - 'A']; 24 25 for (int i = 0; i <= n - k; i++) 26 { 27 for (int j = 0; j < k; j++) 28 h = h << 2 | DNA[i + j]; 29 30 ++cnt[h]; 31 h = 0; 32 } 33 34 for (int i = 0; i < (1 << (k << 1)); i++) if (ans < cnt[i]) 35 ans = cnt[i]; 36 37 printf("%d\n", ans); 38 return 0; 39 }