POJ3080 - Blue Jeans(KMP+二分)

题目大意

求N个字符串的最长公共字串

题解

POJ1226做法一样。。。注意是字典序最小的。。。WA了一次

代码:

#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

using namespace std;

#define  MAXN 65

char p[MAXN],T[MAXN][MAXN];

int f[MAXN];

void getfail(char *p,int len)

{

      int j;

      f[0]=j=-1;

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

      {

          while(j>=0&&p[j+1]!=p[i]) j=f[j];

          if(p[j+1]==p[i]) j++;

          f[i]=j;

      }

}

bool find(char *s,int len,int n)

{

     getfail(s,len);

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

     { 

            int j=-1,lens=strlen(T[t]);

            bool flag=false;

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

            {

                  while(j>=0&&s[j+1]!=T[t][i]) j=f[j];

                  if(s[j+1]==T[t][i]) j++;

                  if(j+1==len)

                  {

                         flag=true;

                         break;

                  }

            }

            if(!flag) return false;

     }

     return true;

}

int main()

{

    int cases;

    scanf("%d",&cases);

    while(cases--)

    {

        int n;

        scanf("%d",&n);

        char s[MAXN],temp[MAXN];

        temp[0]='\0';

        for(int i=0;i<n;i++) scanf("%s",T[i]);

        strcpy(s,T[0]);

        int len=strlen(s);

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

        {

            char ss[MAXN];

            ss[0]='\0';

            int l=i,r=len-1;

            while(l<=r)

            {

                int mid=(l+r)>>1;

                bool flag=find(s+i,mid-i+1,n);

                if(flag)

                {

                    l=mid+1;

                    strncpy(ss,s+i,mid-i+1);

                    ss[mid-i+1]='\0';

                }

                else r=mid-1;

            }

            if(strlen(ss)>strlen(temp)||(strlen(ss)==strlen(temp)&&strcmp(ss,temp)==-1)) strcpy(temp,ss);

        }

        if(strlen(temp)>=3)

            printf("%s\n",temp);

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

    }

    return 0;

}

你可能感兴趣的:(poj)