您的位置:首页 > 其它

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

2017-05-09 18:46 253 查看
碱基

生物学家正在对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
4000
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 stub
Reader.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);
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息