UVA760 DNA Sequencing

Description

多组数据,每组给出两个小写字母组成的字符串,求两个字符串的最长公共子串,如有多个按字典序顺序输出,如没有输出 No common sequence.,每两组数据间输出一个空行,最后一组数据后不应输出空行。

Solution

将两个字符串用分隔符连在一起,求出SA

求出height的最大值,要求这个最大值对应的两个串位于分隔符两侧

所有相同的答案在height数组中都是连续的,遇到相同就可以跳过

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int t,len1,len2,sa[615],buc[615],rk[615],x[615],y[615],height[615],m=131,n,ans;
char S[305],T[305],s[615];
inline int read(){
    int f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')w=(w<<1)+(w<<3)+ch-'0',ch=getchar();
    return f*w;
}
void getsa(){
    m=131;
    for(int i=1;i<=m;i++)buc[i]=0;
    for(int i=1;i<=n;i++)++buc[x[i]=s[i]];
    for(int i=2;i<=m;i++)buc[i]+=buc[i-1];
    for(int i=n;i;i--)sa[buc[x[i]]--]=i;
    for(int k=1;k<=n;k<<=1){
        int num=0;
        for(int i=n-k+1;i<=n;i++)y[++num]=i;
        for(int i=1;i<=n;i++)if(sa[i]>k)y[++num]=sa[i]-k;
        for(int i=1;i<=m;i++)buc[i]=0;
        for(int i=1;i<=n;i++)++buc[x[i]];
        for(int i=2;i<=m;i++)buc[i]+=buc[i-1];
        for(int i=n;i;i--)sa[buc[x[y[i]]]--]=y[i],y[i]=0;
        swap(x,y),x[sa[1]]=1,num=1;
        for(int i=2;i<=n;i++)x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k])?num:++num;
        if(num==n)break;
        m=num;
    }
}
void getheight(){
    int k=0;
    for(int i=1;i<=n;i++)rk[sa[i]]=i;
    for(int i=1;i<=n;i++){
        if(rk[i]==1)continue;
        if(k)--k;
        int j=sa[rk[i]-1];
        while(j+k<=n&&i+k<=n&&s[i+k]==s[j+k])++k;
        height[rk[i]]=k;
    }
}
int main(){
    while(scanf("%s%s",S+1,T+1)!=EOF){
        ans=0,++t,len1=strlen(S+1),len2=strlen(T+1),s[len1+1]='$';
        if(t>1)putchar(10);
        for(int i=1;i<=len1;i++)s[i]=S[i];
        for(int i=1;i<=len2;i++)s[i+len1+1]=T[i];
        n=len1+len2+1,getsa(),getheight();
        for(int i=2;i<=n;i++)if(sa[i-1]<=len1&&sa[i]>len1+1||sa[i-1]>len1+1&&sa[i]<=len1)ans=max(ans,height[i]);
        if(!ans){puts("No common sequence.");continue;}
        for(int i=2;i<=n;i++)if(height[i]==ans){
            int j=i,k=i;
            while(height[j]==ans)++j;
            for(;k<j;k++)if(sa[k-1]<=len1&&sa[k]>len1+1||sa[k-1]>len1+1&&sa[k]<=len1)break;
            if(k!=j){
                for(int p=sa[k];p<sa[k]+ans;p++)putchar(s[p]);
                putchar(10);
            }
            i=j-1;
        }
    }
    return 0;
}
DNA Sequencing

 

posted @ 2021-04-05 23:41  QDK_Storm  阅读(77)  评论(0编辑  收藏  举报