蓝桥杯 2017年试题 历届真题 碱基【第七届】【决赛】c++

题目描述

        生物学家正在对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的余数。

输入与输出示例 

示例1

输入

3 2 2
ATC
TCG
ACG

输出

2

 示例1

输入

4 3 3
AAA
AAAA
AAA
AAA

输出

7

题目分析 

一开始看了样例也没看明白懂题目在说什么

大概描述以下就是在n个生物中取m个生物并能够找到连续k的碱基片段记为找到了1个2m元组

同时若该生物中有多个这种相同的片段 就算作不同的片段(可能没说清楚)

样例分析

样例1

ATC
TCG
ACG

取1号(ATC)和2号(TCG)可找到一个2m元组“TC”

同理 取2号(TCG)和3号(ACG)可找到一个2m元组“CG”

一共就是2个2m元组

样例2

AAA
AAAA
AAA
AAA

取1,2,3或1,2,4或2,3,4都能找到 2 个2m元组(都是以“AAA”为片段的)

因为2可以取前面的“AAA”也可以取后面的“AAA”

而取1,3,4能找到1个2m元组(也是“AAA”片段的)

一共就是7个

 具体代码

#include<iostream>
#include<cstring>
#include<set>
#include<map>
#define ll long long
#define mod 1000000007
using namespace std;
int n, m, k;
string ss[6];
//统计每个字符串中连续的k的字符串片段的个数
map<string, ll>mp[6];
//统计所有字符串的连续的k的字符串片段
set<string>Set;
ll ans;
ll part;
//初始化
void init() {
	for (int i = 0; i < n;i++) {
		for (int j = 0; j <= ss[i].size() - k;j++) {
			string s = ss[i].substr(j, k);
			mp[i][s]++;
			Set.insert(s);
		}
	}
}
void dfs(int idx,int p,ll sum,string str) {
	if (p == m) {
		part += sum;
		return;
	}
	for (int i = idx;i < n;i++) {
		dfs(i + 1, p + 1, sum * mp[i][str], str);
	}
}
int main() {
	cin >> n >> m >> k;
	ans = 0;
	for (int i = 0;i < n;i++)cin >> ss[i];
	init();//初始化
	for (string str:Set) {
		part = 0;//初始化
		for (int i = 0;i <= n - m;i++) {
			if (mp[i].count(str)) {
				dfs(i + 1, 1, mp[i][str],str);
			}
		}
		ans += part;
	}
	cout << ans % mod;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值