POJ 3080 Blue jeanes

传送门 :http://poj.org/problem?id=3080

                         Blue Jeans

Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u
Submit

Status

Practice

POJ 3080
Description
The Genographic Project is a research partnership between IBM and The National Geographic Society that is analyzing DNA from hundreds of thousands of contributors to map how the Earth was populated.

As an IBM researcher, you have been tasked with writing a program that will find commonalities amongst given snippets of DNA that can be correlated with individual survey information to identify new genetic markers.

A DNA base sequence is noted by listing the nitrogen bases in the order in which they are found in the molecule. There are four bases: adenine (A), thymine (T), guanine (G), and cytosine (C). A 6-base DNA sequence could be represented as TAGACC.

Given a set of DNA base sequences, determine the longest series of bases that occurs in all of the sequences.
Input
Input to this problem will begin with a line containing a single integer n indicating the number of datasets. Each dataset consists of the following components:
A single positive integer m (2 <= m <= 10) indicating the number of base sequences in this dataset.
m lines each containing a single base sequence consisting of 60 bases.
Output
For each dataset in the input, output the longest base subsequence common to all of the given base sequences. If the longest common subsequence is less than three bases in length, display the string “no significant commonalities” instead. If multiple subsequences of the same longest length exist, output only the subsequence that comes first in alphabetical order.

Sample Input
3
2
GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
3
GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA
GATACTAGATACTAGATACTAGATACTAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA
GATACCAGATACCAGATACCAGATACCAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA
3
CATCATCATCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
ACATCATCATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACATCATCATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT
Sample Output
no significant commonalities
AGATAC
CATCATCAT

题目有点长,大概就是给你一堆 字符串 每个字符串代表一个DNA 链 求出所以DNA中最长公共DNA

全部以第一个DNA 为母串,将第一个串挨个前缀去匹配。每次记录当前前缀串所匹配的个数。每次比较一下就好,记得这里有个坑点就是如果最大长度一样, 按字典序排序输出最小的。细节看代码。

#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxs=105;
int m,len_pat,mate_length;
int nexts[105];
char s[11][105],result[maxs],pat[maxs];
void kmp_nexts(char *s,int *nx)
{
    int i=0,k=-1;
    nx[0]=-1;
    while(s[i])
    {
        if(k==-1||s[i]==s[k])
            nx[++i]=++k;
        else
            k=nx[k];
    }
}
void kmp()
{
    int i,j,k,match;
    mate_length=100;
    kmp_nexts(pat,nexts);
    for(int i=1;i<m;i++)            //把 s[0] 的后缀 与所有的匹配串匹配一次
    {
        k=0,j=0,match=0;            //每次更新一下,match 代表与当前串匹配的个数
        while(k<60&&j<len_pat)       //len_pat代表后缀串的长度
        {
            if(j==-1||s[i][k]==pat[j])
            {
                k++,j++;
            }
            else
                j=nexts[j];
            if(j>match)
                match=j;
        }
        if(match<mate_length)     //mate_length 是每个后缀串与所有串匹配的最大数
            mate_length=match;
    }
}
int main()
{
    int n,i,j,ans;
    scanf("%d",&n);
    getchar();
    while(n--)
    {
        ans=0;
        scanf("%d",&m);
        getchar();
        for(i=0;i<m;i++)
        {
          scanf("%s",s[i]);
        }
        for(i=0;i<=57;i++)
        {
            strcpy(pat,s[0]+i);      //这里需要想一下,把第一个串的所有 后缀 当做子串,与每个串匹配
            len_pat=60-i;
            kmp();
            if(ans<mate_length)
            {
                ans=mate_length;
                strncpy(result,s[0]+i,ans);        //strncpy(*s,*ss,int len) 把ss中的前len个字符拷贝到s中
                result[ans]='\0';                  // 注意不拷贝 '\0';
            }
            else if(ans==mate_length)
            {
                char temp[maxs];
                strncpy(temp,s[0]+i,ans);               //这里是 有相同最大长度的子串,所以按字典序从小到大排序。
                temp[ans]='\0';
                if(strcmp(result,temp)>0)
                    strcpy(result,temp);
            }
        }
        if(ans<3)
             printf("no significant commonalities\n");
        else
            printf("%s\n",result);
    }
    return 0;
}

你可能感兴趣的:(KMP,poj)