POJ 3080 Blue Jeans (KMP)

求出公共子序列  要求最长  字典序最小

枚举第一串的所有子串   然后对每一个串做KMP。找到目标子串

学会了   strncpy函数的使用   我已可入灵魂   

 

#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>



using namespace std;



char str[20][70];

char tmp[70],ans[70];

int f[70];

int n;



void getfail(char *P)

{

    int m=strlen(P);

    f[0]=0;f[1]=0;

    for(int i=1;i<m;i++)

    {

        int j=f[i];

        while(j&&P[i]!=P[j])j=f[j];

        f[i+1]=P[i]==P[j]?j+1:0;

    }

}



bool find(char *P,char *T)

{

    int n=strlen(T);

    int m=strlen(P);

    getfail(P);

    int j=0;

    for(int i=0;i<n;i++)

    {

        while(j&&P[j]!=T[i])j=f[j];

        if(P[j]==T[i])j++;

        if(j==m)return true;//printf("%d\n",i-m+1);

    }

    return false;

}



bool work(char *tmp,int l)//l : tmp   len: ans

{

    for(int i=2;i<=n;i++)

    {

        if(!find(tmp,str[i]))return false;

    }

    int len=strlen(ans);



    if(l>len)strcpy(ans,tmp);//最长

    else if(l==len && strcmp(tmp,ans)<0)strcpy(ans,tmp);//字典序最小



    return true;

}



int main()

{

    int CASE;

    scanf("%d",&CASE);



    while(CASE--)

    {

        scanf("%d",&n);



        for(int i=1;i<=n;i++)

        scanf("%s",str[i]);



        memset(ans,0,sizeof(ans));



        memset(tmp,0,sizeof(tmp));



        int len=strlen(str[1]);



        for(int i=1;i<=len;i++)

        {

            for(int j=0;j<len-i+1;j++)

            {

                strncpy(tmp,str[1]+j,i);

                work(tmp,i);

            }

        }

        if(strlen(ans)>=3)printf("%s\n",ans);//题目中说要至少3个长度

        else printf("no significant commonalities\n");

    }

    return 0;

}


 

 

你可能感兴趣的:(poj)