2016年第七屆藍橋杯Java程序設計本科B組決賽個人題解彙總:
https://blog.csdn.net/daixinliangwyx/article/details/90169154
第五題
標題:鹼基
交題測試地址:https://www.dotcpp.com/oj/problem1835.html
生物學家正在對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,否則按無效代碼處理。
解法:題目意思要好好理解一下,就是求有多少種DNA序列組合,在每種組合中,每個DNA序列都包含了同一個k長連續鹼基序列子串(同一DNA序列中子串位置不一樣的幾種不會只算做一種,具體看下面樣例2的解釋)。
比如樣例1:這2種組合是(1,2)、(2,3):1串的TC和2串的TC、2串的CG跟3串的CG。
再比如樣例2:這7種組合是(1,2,3)、(1,2,4)、(1,3,4)、(1,2,3)、(1,2,4)、(2,3,4)、(2,3,4),具體解釋一下這7種,至於這裏面重復的組合,是因爲k長相同子串在某個串裏面的位置不一樣:
(1,2,3):1串的"AAA",2串[0,3]位置的"AAA",3串的"AAA";
(1,2,3):1串的"AAA",2串[1,4]位置的"AAA",3串的"AAA";
(1,2,4):1串的"AAA",2串[0,3]位置的"AAA",4串的"AAA";
(1,2,4):1串的"AAA",2串[1,4]位置的"AAA",4串的"AAA";
(2,3,4):2串[0,3]位置的"AAA",3串的"AAA",4串的"AAA";
(2,3,4):2串[1,4]位置的"AAA",3串的"AAA",4串的"AAA";
(1,3,4):1串的"AAA",3串的"AAA",4串的"AAA"。
做起來的話,n和m的範圍都很小,暴搜就行了,先搜出m個DNA序列,然後取這m箇中的第一個DNA序列遍歷找k長的子串,看後面m-1個DNA序列是否都包含這個子串,進行統計即可。
代碼:
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
public class Main {
public static InputReader in = new InputReader(new BufferedInputStream(System.in));
public static PrintWriter out = new PrintWriter(System.out);
public static int n, m, k;
public static long ans, tmp, mod = 1000000007;
public static String str;
public static String[] s = new String[10];
public static int[] a = new int[10];
public static void main(String[] args) {
n = in.nextInt();
m = in.nextInt();
k = in.nextInt();
for (int i = 1; i <= n; i++)
s[i] = in.nextLine();
ans = 0;
dfs(1, 1);
out.println(ans%mod);
out.flush();
out.close();
}
static void dfs(int kk, int p) {
if (kk > m) {
int len = s[a[1]].length();
for (int i = 0; i < len-k+1; i++) {
str = s[a[1]].substring(i, i+k);
tmp = 1;
for (int j = 2; j <= m; j++) {
tmp = (tmp * getStrCount(s[a[j]], str)) % mod;
if (tmp == 0) break;//這些DNA序列裏遇到有不包含str子序列的,後面的DNA序列就不需要繼續查找了,直接break
}
ans = (ans + tmp) % mod;
}
return;
}
for (int i = p; i <= n; i++) {
a[kk] = i;
dfs(kk+1, i+1);
}
}
static long getStrCount(String s1, String s2) {
long sum = 0;
String tmps = s1;
int index = tmps.indexOf(s2);
while (index != -1) {
sum++;
tmps = tmps.substring(index+1);
index = tmps.indexOf(s2);
}
return sum;
}
static class InputReader {
public BufferedReader reader;
public StringTokenizer tokenizer;
public InputReader(InputStream stream) {
reader = new BufferedReader(new InputStreamReader(stream), 32768);
tokenizer = null;
}
public String next() {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
try {
tokenizer = new StringTokenizer(reader.readLine());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
return tokenizer.nextToken();
}
public String nextLine() {
String str = null;
try {
str = reader.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return str;
}
public int nextInt() {
return Integer.parseInt(next());
}
public long nextLong() {
return Long.parseLong(next());
}
public Double nextDouble() {
return Double.parseDouble(next());
}
public BigInteger nextBigInteger() {
return new BigInteger(next());
}
public BigDecimal nextBigDecimal() {
return new BigDecimal(next());
}
}
}
評測結果: