第七届 蓝桥杯 决赛 碱基(哈希,不保证对)

来源:互联网 发布:淘宝客网站模板 编辑:程序博客网 时间:2024/06/04 11:49
碱基


生物学家正在对n个物种进行研究。
其中第i个物种的DNA序列为s[i],其中的第j个碱基为s[i][j],碱基一定是A、T、G、C之一。
生物学家想找到这些生物中一部分生物的一些共性,他们现在关注那些至少在m个生物中出现的长度为k的连续碱基序列。准确的说,科学家关心的序列用2m元组(i1,p1,i2,p2....im,pm)表示,
满足:
1<=i1<i2<....<im<=n;
且对于所有q(0<=q<k), s[i1][p1+q]=s[i2][p2+q]=....=s[im][pm+q]。


现在给定所有生物的DNA序列,请告诉科学家有多少的2m元组是需要关注的。如果两个2m元组有任何一个位置不同,则认为是不同的元组。


【输入格式】
输入的第一行包含三个整数n、m、k,两个整数之间用一个空格分隔,意义如题目所述。
接下来n行,每行一个字符串表示一种生物的DNA序列。
DNA序列从1至n编号,每个序列中的碱基从1开始依次编号,不同的生物的DNA序列长度可能不同。


【输出格式】
输出一个整数,表示关注的元组个数。
答案可能很大,你需要输出答案除以1000000007的余数。


【样例输入】
3 2 2
ATC
TCG
ACG


【样例输出】
2


再例如:
【样例输入】
4 3 3
AAA
AAAA
AAA
AAA


【样例输出】
7




【数据规模与约定】
对于20%的数据,k<=5,所有字符串总长L满足L <=100
对于30%的数据,L<=10000
对于60%的数据,L<=30000
对于100%的数据,n<=5,m<=5,1<=k<=L<=100000
保证所有DNA序列不为空且只会包含’A’ ’G’ ’C’ ’T’四种字母


资源约定:
峰值内存消耗 < 256M
CPU消耗  < 1000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。


所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。
注意:不要使用package语句。不要使用jdk1.7及以上版本的特性。

注意:主类的名字必须是:Main,否则按无效代码处理。



后缀数组似乎可以直接套,然而我还不太会写,所以这道还是用相对熟练一点的哈希来做~~~(样例过了,实际

无数据供测,不知道正确与否)


首先看到题目得分析其题意,分析出样例输出是怎样得到的。不妨将n个字符串以str1...strn表示,则

第一个样例是str1与str2这两个字符串长度为2的TC匹配,str2与str3这两个字符串长度为2的CG匹配,共2个要关注

第二个样例是str1、str3、str4有1个AAA,str2中有2个AAA。将总的字符串再分为m元组,(1,2,3)中需要关注

的2m元组有1*2*1个,(1,2,4)中有1*2*1个,(1,3,4)中有1*1*1个,(2,3,4)中有1*2*1个,加起来(1*2*1)*3+1*1*1=7(个)


思路就是,对每个DNA序列,从第一个字符开始,取长度为k的子串,一个一个取过去。关于定长字符串哈希的

写法部分,可见我poj1200解题报告,这里不再赘述。对于这道题,我是用HashMap,Key表示子串哈希值,Value

即哈希值均为Key子串个数(这种题一般来说子串不同哈希值亦不同,子串相同哈希值亦相同),然后边扫边更新。至于

HashSet,则是用来存储这些Key值,即不同哈希值。每扫完一个字符串,就将HashSet里存储的值取出来放到数组

里方便之后处理。(有点类似我上一篇的操作,只不过上一篇用的是TreeSet)

对第一个字符串这样操作,后面的几个字符串亦是如此。将所有n个字符串处理完了,接下来,就是组合搜索,先

从n个字符串里选取m个字符串。选完了以后,以第一个字符串为参考标准,假设其某个哈希值key1对应的value为v1

而剩余m-1个字符串里,哈希值均为key1的子串个数分别为v2,v3,...,vm,则又可得到v1*v2*...*vm个2m元组。这样

不断更新ans即可。这道题还有一个,就是数字较大可能溢出,取模的同时还要用long类型存值


代码如下:

import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;import java.util.HashMap;import java.util.HashSet;import java.util.Iterator;import java.util.StringTokenizer;class Reader {static BufferedReader reader;static StringTokenizer tokenizer;static void init(InputStream input) {reader = new BufferedReader(new InputStreamReader(input));tokenizer = new StringTokenizer("");}static String next() throws IOException {while (!tokenizer.hasMoreTokens()) {tokenizer = new StringTokenizer(reader.readLine());}return tokenizer.nextToken();}static int nextInt() throws IOException {return Integer.parseInt(next());}}public class MatchP5 {/** * @param args */static long monum = Integer.MAX_VALUE;static long mulnum = 100000007;static long ansmo = 1000000007;static long val, mval, ans, cnt;static int n, m, k, len, nums, v;static char ch[][];static long chval[];static String str;static int arr[], hashnum[], size[];static int hval[][];static HashMap<Integer, Integer> hashMap[];static HashSet<Integer> hashSet[];    static boolean flag;private static void dfs(int num, int st) {if (num == m + 1) {for (int i = 1; i <= size[arr[1]]; i++) {v = hval[arr[1]][i];cnt = (long) hashMap[arr[1]].get(v) % ansmo;flag=true;for (int j = 2; j <= m; j++)if (hashMap[arr[j]].containsKey(v))cnt = cnt * (long) hashMap[arr[j]].get(v) % ansmo;else {flag=false;break;}if (flag) ans = ans + cnt;}return;}for (int i = st; i <= n - m + num; i++) {arr[num] = i;dfs(num + 1, i + 1);}}private static void dealStr(int num) {val = 0;len = ch[num].length;if (len < k)return;mval = 1;for (int i = 1; i <= k; i++) {val = (val * mulnum + chval[ch[num][i - 1]]) % monum;mval = (mval * mulnum) % monum;}hashMap[num].put((int) val, 1);hashSet[num].add((int) val);for (int i = k + 1; i <= len; i++) {val = (val * mulnum + chval[ch[num][i - 1]]) % monum;val = ((val - chval[ch[num][i - k - 1]] * mval) % monum + monum)% monum;if (!hashMap[num].containsKey((int) val)) {hashMap[num].put((int) val, 1);hashSet[num].add((int) val);} else {nums = hashMap[num].get((int) val);hashMap[num].put((int) val, nums + 1);}}size[num] = hashSet[num].size();hval[num] = new int[size[num] + 1];Iterator<Integer> iter = hashSet[num].iterator();int cnt = 0;while (iter.hasNext()) {cnt++;hval[num][cnt] = iter.next();}}public static void main(String[] args) throws IOException {// TODO Auto-generated method stubReader.init(System.in);n = Reader.nextInt();m = Reader.nextInt();k = Reader.nextInt();ch = new char[n + 1][];for (int i = 1; i <= n; i++) {str = Reader.next();ch[i] = str.toCharArray();}hashMap = new HashMap[n + 1];hashSet = new HashSet[n + 1];hval = new int[n + 1][];size = new int[n + 1];chval = new long[200];chval['A'] = 0;chval['T'] = 1;chval['G'] = 2;chval['C'] = 3;for (int i = 1; i <= n; i++)hashMap[i] = new HashMap<Integer, Integer>();for (int i = 1; i <= n; i++)hashSet[i] = new HashSet<Integer>();arr = new int[m + 1];for (int i = 1; i <= n; i++)dealStr(i);ans = 0;dfs(1, 1);System.out.println(ans);}}


0 0
原创粉丝点击