首页 > 其他分享 >Luogu P4591 [TJOI2018]碱基序列

Luogu P4591 [TJOI2018]碱基序列

时间:2023-06-10 19:24:05浏览次数:44  
标签:AA P4591 ABC AAA int Luogu 碱基 样例 TJOI2018

[TJOI2018]碱基序列

题目描述

小豆参加了生物实验室。在实验室里,他主要研究蛋白质。他现在研究的蛋白质是由\(k\)个氨基酸按一定顺序构成的。每一个氨基酸都可能有\(a\)种碱基序列\(s_{i,j}\)构成。

现在小豆有一个碱基串\(s\),小豆想知道在这个碱基上都多少中不同的组合方式可能得到这个蛋白质。即求由\(k\)段字符串有序合并成的字符串\(s_1\),有多少种不同方式能够匹配字符串\(s\),其中\(k\)段字符串的选法不同,或者与\(s\)匹配上的位置不同认为是不同的方式。

输入格式

第一行一个数,表示这个蛋白质由\(k\)个氨基酸。

第二行一个字符串\(s\),表示小豆现在有的碱基串。

第三行开始接下来\(k\)行表示第\(i\)个氨基酸可能的碱基序列,对于第\(i\)个氨基酸,\(a_i\)表示这个氨基酸可能的碱基序列种数,接下来\(a_i\)个字符串表示这\(a_i\)种可能的碱基序列,用空格隔开。

输出格式

输出一个数目标是不同的方案数(不同的方案数是指不同的子碱基串或者相同的碱基串不同的氨基酸排列方式)

答案对\(10^9+7\)取模

样例 #1

样例输入 #1

2
ABC
2 A AB
2 C BC

样例输出 #1

2

样例 #2

样例输入 #2

2
AAA
2 A AA
2 A AA

样例输出 #2

4

提示

样例解释1

第一个选\(A\)第二个选\(C\),得到\(AC\)能够与\(ABC\)产生\(0\)中匹配方式

第一个选\(A\)第二个选\(BC\),得到\(ABC\)能够与\(ABC\)产生\(1\)中匹配方式

第一个选\(AB\)第二个选\(C\),得到\(ABC\)能够与\(ABC\)产生\(1\)中匹配方式

第一个选\(AB\)第二个选\(BC\),得到\(ABBC\)能够与\(ABC\)产生\(0\)中匹配方式

所以一共2种

样例解释2

第一个选\(A\)第二个选\(A\),得到\(AA\)能够与\(AAA\)产生\(2\)中匹配方式

第一个选\(A\)第二个选\(AA\),得到\(AAA\)能够与\(AAA\)产生\(1\)中匹配方式

第一个选\(AA\)第二个选\(A\),得到\(AAA\)能够与\(AAA\)产生\(1\)中匹配方式

第一个选\(AA\)第二个选\(AA\),得到\(AAAA\)能够与\(AAA\)产生\(0\)中匹配方式

所以一共4种

数据范围

对于\(30\%\)的数据,\(1\leq k\leq25,|s|\leq10000,a_i\leq3\)

对于\(100\%\)的数据,\(1\leq k\leq100,|s|\leq10000,a_i\leq10\)

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>

using namespace std;

typedef unsigned long long ull;
int k, ans, mod = 1000000007;
int cnt[5211314];
ull base[5211314], num[5211314], pre[521][1314];
string seq[521][13], amino;
int dp[521][131400];
//dp[i][j]表示到第i层碱基序列 蛋白质在j位置上对应的最长连接序列

int main() {
	scanf("%d", &k);
	cin >> amino;
	base[0] = 1;
	for (int i = 1; i <= amino.size(); ++ i) {
		base[i] = base[i - 1] * 131;
		//提前预处理出来base
	}
	for (int i = 1, temp; i <= k; ++ i) {
		scanf("%d", &temp);
		cnt[i] = temp;
		for (int j = 1; j <= cnt[i]; ++ j) {
			cin >> seq[i][j];
			for (int q = 0; q < seq[i][j].size(); ++ q) {
				pre[i][j] = pre[i][j] * base[1] + (ull)seq[i][j][q];
				//进行哈希预处理
			}
		}
	}
	num[0] = (ull)amino[0];
	for (int i = 1; i < amino.size(); ++ i) {
		num[i] = num[i - 1] * base[1] + (ull)amino[i];
	}
	for (int i = 0; i <= amino.size(); ++ i) dp[0][i] = 1;
	for (int i = 1; i <= k; ++ i) {
		//在第i层
		for (int j = 1, len; j <= cnt[i]; ++ j) {
			//第j个碱基序列
			len = seq[i][j].size();
			for (int q = len - 1, l, r; q < amino.size(); ++ q) {
				//将当前碱基序列与蛋白质的每一段相同长度的序列进行比较
				ull temp;
				l = q - len + 1, r = q;
				if (l == 0) temp = num[q];
				else {
					temp = num[r] - num[l - 1] * base[r - l + 1];
				}
				if (temp == pre[i][j]) {
					//若相同则从上一状态转移
					dp[i][q + 1] += dp[i - 1][q - len + 1];
					dp[i][q + 1] %= mod;
				}
			}
		}
	}
	for (int i = 0; i < amino.size(); ++ i) {
		ans += dp[k][i + 1];
		//找对应的值的和
		ans %= mod;
	}
	printf("%d\n", ans);
	return 0;
} 

标签:AA,P4591,ABC,AAA,int,Luogu,碱基,样例,TJOI2018
From: https://www.cnblogs.com/jueqingfeng/p/17471779.html

相关文章

  • Luogu P4159 [SCOI2009] 迷路
    [SCOI2009]迷路题目背景windy在有向图中迷路了。题目描述该有向图有\(n\)个节点,节点从\(1\)至\(n\)编号,windy从节点\(1\)出发,他必须恰好在\(t\)时刻到达节点\(n\)。现在给出该有向图,你能告诉windy总共有多少种不同的路径吗?答案对\(2009\)取模。注意:windy......
  • Luogu P1939 【模板】矩阵加速(数列)
    【模板】矩阵加速(数列)题目描述已知一个数列\(a\),它满足:\[a_x=\begin{cases}1&x\in\{1,2,3\}\\a_{x-1}+a_{x-3}&x\geq4\end{cases}\]求\(a\)数列的第\(n\)项对\(10^9+7\)取余的值。输入格式第一行一个整数\(T\),表示询问个数。以下\(T\)行,每行一个正......
  • Luogu P3390 【模板】矩阵快速幂
    【模板】矩阵快速幂题目背景一个\(m\timesn\)的矩阵是一个由\(m\)行\(n\)列元素排列成的矩形阵列。即形如\[A=\begin{bmatrix}a_{11}&a_{12}&\cdots&a_{1n}\\a_{21}&a_{22}&\cdots&a_{2n}\\\vdots&\vdots&\ddots&......
  • Luogu B2105 矩阵乘法(模板)
    矩阵乘法题目描述计算两个矩阵的乘法。\(n\timesm\)阶的矩阵\(A\)乘以\(m\timesk\)阶的矩阵\(B\)得到的矩阵\(C\)是\(n\timesk\)阶的,且\(C[i][j]=A[i][0]\timesB[0][j]+A[i][1]\timesB[1][j]+\)……\(+A[i][m-1]\timesB[m-1][j](C[i][j]\)表示\(C\)......
  • Luogu P4219 [BJOI2014]大融合
    [BJOI2014]大融合题目描述小强要在\(N\)个孤立的星球上建立起一套通信系统。这套通信系统就是连接\(N\)个点的一个树。这个树的边是一条一条添加上去的。在某个时刻,一条边的负载就是它所在的当前能够联通的树上路过它的简单路径的数量。例如,在上图中,现在一共有了\(5\)......
  • Luogu P4577 [FJOI2018] 领导集团问题
    [FJOI2018]领导集团问题题目描述一个公司的组织领导架构可以用一棵领导树来表示。公司的每个成员对应于树中一个结点\(v_i\),且每个成员都有响应的级别\(w_i\)。越高层的领导,其级别值\(w_i\)越小。树中任何两个结点之间有边相连,则表示与结点相应的两个成员属于同一部门。领......
  • Luogu P5446 [THUPC2018] 绿绿和串串
    根据题目能发现一个性质,设转化前的字符串为\(s\),转化后的字符串为\(s'\),则\(s'_{|s|}\)为\(s'\)的中心,即\(s'_{|s|}\)求出来的回文串左边界为\(1\)右边界为\(|s'|\)找出这个性质就挺简单了,考虑先对给出的\(S\)用\(\text{manacher}\)求出每个节点\(i\)对应的左边......
  • Luogu P3224 [HNOI2012]永无乡
    [HNOI2012]永无乡题目描述永无乡包含\(n\)座岛,编号从\(1\)到\(n\),每座岛都有自己的独一无二的重要度,按照重要度可以将这\(n\)座岛排名,名次用\(1\)到\(n\)来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛到达另一个岛。如果从岛\(a\)出发经过若干座(含\(0\)......
  • [刷题笔记] Luogu P3073 [USACO13FEB]Tractor S
    ProblemSolution和汽车拉力比赛差不多,思路都是二分,二分\(d\),但是汽车拉力比赛从一个路标开始搜即可,本题没有给定起点。一条合法路径起点是未知的,不得随便从一个点开始搜,否则可能找不到正确路径。怎么处理呢?容易想到对于每一个二分的\(d\),开一个\(n^2\)的循环,从每一个点开始搜......
  • Luogu P3605 [USACO17JAN]Promotion Counting P
    [USACO17JAN]PromotionCountingP题目描述Thecowshaveonceagaintriedtoformastartupcompany,failingtorememberfrompastexperiencethatcowsmaketerriblemanagers!Thecows,convenientlynumbered\(1\ldotsN\)(\(1\leqN\leq100,000\)),o......