暴力枚举(字符串匹配)-Blue Jeans POJ - 3080
题目:
Genographic项目是IBM与国家地理学会之间的研究合作伙伴关系,该合作伙伴正在分析数十万贡献者的DNA,以绘制地球的分布图。
作为IBM研究人员,您的任务是编写一个程序,该程序将在给定的DNA片段之间找到共同点,这些片段可以与单个调查信息相关联以识别新的遗传标记。
通过在分子中发现氮碱基的顺序列出DNA碱基序列,可以注意到DNA碱基序列。有四个碱基:腺嘌呤(A),胸腺嘧啶(T),鸟嘌呤(G)和胞嘧啶(C)。6个碱基的DNA序列可以表示为TAGACC。
给定一组DNA碱基序列,请确定出现在所有序列中的最长碱基序列。
Input
该问题的输入将从包含单个整数n的行开始,该整数指示数据集的数量。每个数据集都包含以下数据:
单个正整数m(2 <= m <= 10)指示此数据集中的碱基序列数。
m行,每个行包含一个由60个碱基组成的单个碱基序列。
Output
对于输入中的每个数据集,输出所有给定碱基序列共有的最长碱基子序列。如果最长的公共子序列的长度小于3个碱基,则显示字符串“no significant commonalities”。如果存在多个最长长度相同的子序列,则仅输出按字典序最小的子序列。
Sample Input
3
2
GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
3
GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA
GATACTAGATACTAGATACTAGATACTAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA
GATACCAGATACCAGATACCAGATACCAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA
3
CATCATCATCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
ACATCATCATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACATCATCATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
Sample Output
no significant commonalities
AGATAC
CATCATCAT
题意:
输 入 m 个 长 度 为 60 的 字 符 串 , 判 断 能 否 在 m 个 串 中 找 出 共 同 的 长 度 大 于 等 于 3 的 子 串 。 输入m个长度为60的字符串,判断能否在m个串中找出共同的长度大于等于3的子串。 输入m个长度为60的字符串,判断能否在m个串中找出共同的长度大于等于3的子串。
题解:
暴 力 枚 举 。 暴力枚举。 暴力枚举。
① 、 把 第 一 个 串 看 作 模 式 串 , 第 一 层 从 60 到 3 枚 举 子 串 的 长 度 k 。 ② 、 第 二 层 枚 举 模 式 串 的 起 点 i 。 截 取 长 度 为 k 的 子 串 t m p 。 ③ 、 对 剩 下 m − 1 个 串 进 行 匹 配 , 匹 配 成 功 的 标 志 是 指 针 j = m + 1 , 把 匹 配 成 功 的 答 案 存 入 a n s 。 同 时 要 注 意 a n s 的 字 典 序 未 必 最 小 , 因 此 要 在 当 前 k 循 环 内 继 续 更 新 。 在 k 的 某 一 趟 循 环 中 , 若 能 匹 配 成 功 , 那 么 这 趟 循 环 结 束 后 必 然 得 出 答 案 。 ④ 、 判 断 能 否 找 到 大 于 等 于 3 的 共 同 子 串 的 标 志 是 a n s 是 否 为 空 。 ①、把第一个串看作模式串,第一层从60到3枚举子串的长度k。\\②、第二层枚举模式串的起点i。截取长度为k的子串tmp。\\③、对剩下m-1个串进行匹配,匹配成功的标志是指针j=m+1,把匹配成功的答案存入ans。\\ \qquad同时要注意ans的字典序未必最小,因此要在当前k循环内继续更新。\\ \qquad在k的某一趟循环中,若能匹配成功,那么这趟循环结束后必然得出答案。\\④、判断能否找到大于等于3的共同子串的标志是ans是否为空。 ①、把第一个串看作模式串,第一层从60到3枚举子串的长度k。②、第二层枚举模式串的起点i。截取长度为k的子串tmp。③、对剩下m−1个串进行匹配,匹配成功的标志是指针j=m+1,把匹配成功的答案存入ans。同时要注意ans的字典序未必最小,因此要在当前k循环内继续更新。在k的某一趟循环中,若能匹配成功,那么这趟循环结束后必然得出答案。④、判断能否找到大于等于3的共同子串的标志是ans是否为空。
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ll long long
#define inf 0x7fffffff
using namespace std;
const int M=11;
int T,m;
string s[M];
int main()
{
cin>>T;
while(T--)
{
scanf("%d",&m);
for(int i=1;i<=m;i++)
cin>>s[i];
string ans="";
for(int k=60;k>=3;k--) ///枚举最长长度
{
for(int i=0;i+k<=60;i++) ///枚举模式串的起点
{
string tmp=s[1].substr(i,k);
int j;
for(j=2;j<=m;j++) ///枚举剩下的m-1个串
{
if(s[j].find(tmp,0)==-1)
break;
}
if(j==m+1&&(ans.empty() || ans>tmp )) ///j==m+1则说明以i为起点长度为k的子串与剩下m-1个串都匹配,
ans=tmp; ///这里不能break,还要继续往下找字典序更小的
}
if(!ans.empty()) break; ///非空,说明已经找到,第一次找到的必然是长度最大的
}
if(ans.empty()) cout<<"no significant commonalities"<<endl;
else cout<<ans<<endl;
}
return 0;
}