题目描述
农夫约翰拥有 N 头有斑点的牛和 N 头没有斑点的牛。
他刚刚完成了牛遗传学课程,他确信奶牛上的斑点是由牛基因组突变引起的。
农夫约翰花了大价钱对他的奶牛的基因组进行了测序。
每个基因组都是一个由四个字符 A,C,G,T 构成的长度为 M 的字符串。
当他统计得到的奶牛的基因组序列时,可以得到一个如下所示的表:(此时,N=3)
位 置: 1 2 3 4 5 6 7 … M
斑点牛 1: A A T C C C A … T
斑点牛 2: G A T T G C A … A
斑点牛 3: G G T C G C A … A
普通牛 1: A C T C C C A … G
普通牛 2: A G T T G C A … T
普通牛 3: A G T T C C A … T
通过仔细观察该表,他发现通过位置 2 和位置 4 的字符足以判断奶牛是否存在斑点。
也就是说,仅通过查看这两个位置上的字符,农夫约翰就可以判断他的哪些奶牛有斑点,哪些没有斑点。
例如,如果他看到 G 和 C,他就知道那头奶牛一定是有斑点的。
约翰坚信是否存在斑点不仅仅可以通过基因组中的一个或两个位置来判断,还可以通过观察三个不同的位置来做出判断。
请帮助他求出共有多少组三个不同的位置可以用来判断是否存在斑点。
样例
输入格式
第一行包含整数 N 和 M。
接下来 N 行,每行包含一个长度为 M 的字符串,用来描述斑点牛的基因组序列。
再接下来 N 行,每行包含一个长度为 M 的字符串,用来描述普通牛的基因组序列。
输出格式
输出可以用来判断是否存在斑点的三个不同位置的组数。
数据范围
1≤N≤500,
3≤M≤50
输入样例:
3 8
AATCCCAT
GATTGCAA
GGTCGCAA
ACTCCCAG
ACTCGCAT
ACTTCCAT
输出样例:
22
算法1
(暴力枚举) $O(nm^3)$
这个题是个模拟题目,我们去枚举任意三列,然后将第一行到第n行的中所有出现的字符标记为已经出现过,然后去看后n行是否出现过,如果没有出现过,则是一个符合条件的基因组,然后枚举其它列就可以了,为了快速去判断是否出现,我们可以将字符映射为一个整数。
C++ 代码
#include<bits/stdc++.h>
using namespace std;
const int N=1010,M=55;
int f[N][M];
int st[30][30][30];
int main()
{
int n,m;
cin>>n>>m;
string str;
for(int i=1;i<=2*n;i++)
{
cin>>str;
for(int j=0;j<m;j++)
f[i][j]=str[j]-'A';
}
int ans=0;
for(int i=0;i<m;i++)
for(int j=i+1;j<m;j++)
for(int k=j+1;k<m;k++)
{
memset(st,0,sizeof st);
for(int l=1;l<=n;l++)
st[f[l][i]][f[l][j]][f[l][k]]=1;
int flag=1;
for(int l=n+1;l<=2*n;l++)
if(st[f[l][i]][f[l][j]][f[l][k]])
flag=0;
if(flag) ans++;
}
cout<<ans<<endl;
return 0;
}