P3670 [USACO17OPEN] Bovine Genomics S 题解
题意
给定 \(2\) 组字符串,每组 \(n\) 个,每个字符串包含 \(m\) 个字符。
我们称一个三元组 \((i,j,k)\) 是合法的,当且仅当第二组的每个字符串中下标为 \((i,j,k)\) 的字符拼成的字符串与第一组的每个字符串中下标为 \((i,j,k)\) 的字符拼成的字符串均不相等。
现在需要你对于给定的 \(2\) 组字符串,找出所有合法的三元组 \((i,j,k)\) 的数量。
分析
因为观察到题目中 \(n,m\) 的数据范围都很小,所以我们考虑直接朴素枚举三元组 \((i,j,k)\),再依次检查合法性。
在检查三元组 \((i,j,k)\) 的合法性时,我们可以建立一个标记数组 \(vis\):
-
首先遍历第一组字符串,对于第 \(x\) 个字符串 \(s_x\),将 \(vis_{s_{x,i},s_{x,j},s_{x,k}}\) 标记为 \(1\)。
-
再遍历第二组字符串,对于第 \(x\) 个字符串 \(s_x\),若 \(vis_{s_{x,i},s_{x,j},s_{x,k}}=1\)(已被标记),则直接继续枚举下一个三元组。
-
否则,若第二组字符串遍历完成后仍没有被标记过的,将答案累加。
需要注意的细节是,我们可以将字符串中包含的 A
、C
、G
、T
字母映射为 \(0\)、\(1\)、\(2\)、\(3\) 四个数字,从而将字符矩阵转换为整数矩阵,方便存储。
代码
#include<bits/stdc++.h> using namespace std; int n,m,ans,num[31]; //num表示映射数组 int a[531][131],b[531][131]; //a,b是由字符矩阵转换为的整数矩阵 bool vis[31][31][31]; //vis是标记数组 bool check(int x,int y,int z){ //检查三元组(x,y,z)是否合法 memset(vis,0,sizeof(vis)); //注意清空 for(int i=1;i<=n;i++) vis[a[i][x]][a[i][y]][a[i][z]]=1; //标记 for(int i=1;i<=n;i++) if(vis[b[i][x]][b[i][y]][b[i][z]]) //被标记过了 return 0; return 1; } int main(){ cin>>n>>m; num['A']=0,num['C']=1,num['G']=2,num['T']=3; //映射字母 for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ char c; cin>>c; a[i][j]=num[c]; //转为整数矩阵 } for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ char c; cin>>c; b[i][j]=num[c]; //同上 } for(int i=1;i<=m;i++) //枚举三元组 for(int j=i+1;j<=m;j++) for(int k=j+1;k<=m;k++) if(check(i,j,k)) ans++; //若合法则累加 cout<<ans; return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】