zoukankan      html  css  js  c++  java
  • POJ1226

    题目大意

    给定n个字符串,字符串可逆序可顺序,求它们的最长公共子串

    题解

    在输入的过程中记录一下最短的那个字符串,然后枚举起点,然后进行二分求出子串末位置,然后再验证是否是公共子串,记录最长的公共子串就是最终答案~~~~时间复杂度为O(N^3*logn)

    代码:

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    #define  MAXN 105
    #define INF 0x3f3f3f3f
    char 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 i=0;i<n;i++)
        {
            int j=-1,lt=strlen(T[i]);
            bool flag1=false,flag2=false;
            for(int t=0;t<lt;t++)
            {
                while(j>=0&&s[j+1]!=T[i][t]) j=f[j];
                if(s[j+1]==T[i][t]) j++;
                if(j+1==len) 
                {
                    flag1=true;
                    break;
                }
            }
            char ss[MAXN];
            strcpy(ss,T[i]);
            reverse(ss,ss+lt);
            j=-1;
            for(int t=0;t<lt;t++)
            {
                while(j>=0&&s[j+1]!=ss[t]) j=f[j];
                if(s[j+1]==ss[t]) j++;
                if(j+1==len) 
                {
                    flag2=true;
                    break;
                }
            }
            if(!flag1&&!flag2) return false;
        }
        return true;
    
    }
    int main()
    {
        int cases;
        scanf("%d",&cases);
        while(cases--)
        {
            int n,maxlen=-INF,len=INF;
            char s[MAXN];
            scanf("%d",&n);
            for(int i=0;i<n;i++)
            {
                scanf("%s",T[i]);
                if(len>strlen(T[i]))
                {
                    len=strlen(T[i]);
                    strcpy(s,T[i]);
                }
            }
            for(int i=0;i<len;i++)
            {
                int l=i,r=len-1,lens=-INF;
                while(l<=r)
                {
                    int mid=(l+r)>>1;
                    bool flag=find(s+i,mid-i+1,n);
                    if(flag)
                    {
                        l=mid+1;
                        lens=mid-i+1;
                    }
                    else
                        r=mid-1;
                    if(lens!=-INF&&lens>maxlen) maxlen=lens;
                }
            }
            if(maxlen!=-INF)
                printf("%d
    ",maxlen);
            else
            {
                printf("0
    ");
            }
        }
        return 0;
    }
  • 相关阅读:
    夜半饮酒
    邀你到成都来
    成都,我的天堂
    真不想松开你的手
    创业,你懂如何求人办事么?
    只要你愿意
    【五月的歌】重振山河
    成都,我爱你
    就算忘了自己也忘不了你
    假如
  • 原文地址:https://www.cnblogs.com/zjbztianya/p/3324449.html
Copyright © 2011-2022 走看看