碱基序列

题目描述

小豆参加了生物实验室。在实验室里,他主要研究蛋白质。他现在研究的蛋白质是由$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:
复制

2
ABC
2 A AB
2 C BC
输出样例#1:
复制

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$

题解

参照bestfy的题解。

设f[i][j]表示使用前i个模式串,匹配前j位的贡献。对每个模式串的每种可能转移,使用hash判断是否匹配。

复杂度O(|S|×∑ai)。

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
rg T data=0,w=1;rg char ch=getchar();
for(;!isdigit(ch);ch=getchar())if(ch=='-') w=-w;
for(;isdigit(ch);ch=getchar()) data=data*10+ch-'0';
return data*w;
}
template<class T>il T read(rg T&x) {return x=read<T>();}
typedef long long ll;
using namespace std; co int N=1e4+2,P=131,mod=1e9+7;
il int add(int x,int y) {return (x+=y)>=mod?x-mod:x;}
il int mul(int x,int y) {return (ll)x*y%mod;}
int m,n,h[N],p[N];
char s[N];
il int calc(int l,int r){
return add(h[r],mod-mul(h[l-1],p[r-l+1]));
}
int now,f[2][N]; int main(){
read(m);
scanf("%s",s+1),n=strlen(s+1);
p[0]=1;
for(int i=1;i<=n;++i){
p[i]=mul(p[i-1],P);
h[i]=add(mul(h[i-1],P),s[i]);
}
fill(f[0],f[0]+n+1,1);
while(m--){
now^=1,fill(f[now],f[now]+n+1,0); // edit 1:clear from 0
for(int a=read<int>(),l;a--;){
scanf("%s",s+1),l=strlen(s+1);
int hash=0;
for(int i=1;i<=l;++i) hash=add(mul(hash,P),s[i]);
for(int i=1;i<=n-l+1;++i)if(calc(i,i+l-1)==hash)
f[now][i+l-1]=add(f[now][i+l-1],f[now^1][i-1]);
}
}
int ans=0;
for(int i=1;i<=n;++i) ans=add(ans,f[now][i]);
printf("%d\n",ans);
return 0;
}

「TJOI2018」str的更多相关文章

  1. loj2576 「TJOI2018」str

    link 题意: 给一个模板串s和n个模式串,每个模式串有$a_i$种可取的串.现在要将n个模式串每个任取一种它可取的串,连接起来,记为串t,那么这种连接方式对答案的贡献为t在s中出现的次数.问所有连 ...

  2. loj#2574. 「TJOI2018」智力竞赛 (路径覆盖)

    目录 题目链接 题解 代码 题目链接 loj#2574. 「TJOI2018」智力竞赛 题解 就是求可重路径覆盖之后最大化剩余点的最小权值 二分答案后就是一个可重复路径覆盖 处理出可达点做二分图匹配就 ...

  3. 2018.06.26「TJOI2018」数学计算(线段树)

    描述 小豆现在有一个数 xxx ,初始值为 111 . 小豆有 QQQ 次操作,操作有两种类型: 111 $ m$ : x=x×mx=x×mx=x×m ,输出 xxx modmodmod MMM : ...

  4. 【LOJ】#2574. 「TJOI2018」智力竞赛

    题解 二分答案 求最小路径点覆盖 由于这里最小路径点覆盖,点是可重的,用floyd求出传递闭包(也就是求出,哪两点之间是可达的) 最后用这个floyd求出的数组建出一个新图,在这个图上跑普通的最小路径 ...

  5. Loj #3057. 「HNOI2019」校园旅行

    Loj #3057. 「HNOI2019」校园旅行 某学校的每个建筑都有一个独特的编号.一天你在校园里无聊,决定在校园内随意地漫步. 你已经在校园里呆过一段时间,对校园内每个建筑的编号非常熟悉,于是你 ...

  6. LOJ #6436. 「PKUSC2018」神仙的游戏(字符串+NTT)

    题面 LOJ #6436. 「PKUSC2018」神仙的游戏 题解 参考 yyb 的口中的长郡最强选手 租酥雨大佬的博客 ... 一开始以为 通配符匹配 就是类似于 BZOJ 4259: 残缺的字符串 ...

  7. 「HAOI2018」字串覆盖

    「HAOI2018」字串覆盖 题意: ​ 给你两个字符串,长度都为\(N\),以及一个参数\(K\),有\(M\)个询问,每次给你一个\(B\)串的一个子串,问用这个字串去覆盖\(A\)串一段区间的最 ...

  8. 「HAOI2016」字符合并

    「HAOI2016」字符合并 题意: ​ 有一个长度为\(n\)的\(01\)串,你可以每次将相邻的\(k\)个字符合并,得到一个新的字符并获得一定分数.得到的新字符和分数由这\(k\)个字符确定.你 ...

  9. 「 深入浅出 」集合Set

    系列文章 「 深入浅出 」集合List 「 深入浅出 」java集合Collection和Map Set继承自Collection接口,不能包含有重复元素.本篇文章主要讲Set中三个比较重要的实现类: ...

随机推荐

  1. layui父页面执行子页面方法

    parent.window[layero.find('iframe')[0]['name']].子页面方法(); layero.find('iframe')[0].contentWindow.子页面方 ...

  2. linux 软连接 ln -s

    <pre>linux 软连接 ln -sln -s /home/ /home/ss/</pre> 按照win的说法就是创建快捷方式在/home/ss/ 文件夹里(名字就是hom ...

  3. GroupBy之后加ToList和不加ToList有什么区别吗?

        class Program    {        static void Main(string[] args)        {             List<Person> ...

  4. LeetCode 503. 下一个更大元素 II(Next Greater Element II)

    503. 下一个更大元素 II 503. Next Greater Element II 题目描述 给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素.数字 ...

  5. 喜马拉雅 FM 已购付费音频下载

    如何下载在喜马拉雅 FM 中已购买的付费音频.之前想分享自己购买的付费音频给朋友听,碍于喜马拉雅 FM 的音频不能直接导出,所以准备自己搞个下载的小软件. 仅可下载已购买的付费音频.当然,如果你是会员 ...

  6. 《PHP - 信号/基本操作/配置》

    一:PHP 信号 - SIGINT / SIGTERM / SIGQUIT - 退出FPM,在master收到退出信号后将向所有的worker进程发送退出信号,然后master退出. - SIGUSR ...

  7. SQL——WHERE子句

    一.WHERE字句的基本用法 WHERE字句用于筛选数据,提取满足条件的记录. WHERE字句的基本用法: SELECT * from 表名 WHERE 条件语句; 二.WHERE字句与删改查 演示s ...

  8. Linux删除含有特殊符号文件名的文件

    1. 文件名含有特殊字符,直接使用 rm 可能删除不了,可以使用如下方法: 1) 使用 ls -i 查处该文件的 inode 号,假设为123    2) 使用find命令删除: rm `find . ...

  9. MySQL 总结篇 [在Oracle基础上学习的MySQL]

    一.学习环境 MySQL 5.7社区版 Navicat for MySQL 百度网盘下载链接:https://pan.baidu.com/s/1yGnznwoZ8CaMgrCsDBhKAQ 二.MyS ...

  10. Hadoop 系列(六)—— HDFS 常用 Shell 命令

    一.基本命令 打开 Hbase Shell: # hbase shell 1.1 获取帮助 # 获取帮助 help # 获取命令的详细信息 help 'status' 1.2 查看服务器状态 stat ...