Blue Jeans POJ - 3080 (多个字符串的最长公共子串)

版权声明: https://blog.csdn.net/sgh666666/article/details/82425478

题意:

      给定n个字符串,要你求出这n个字符串的最长公共子串,如果存在多个输出字典序最小的那个.

分析:

       KMP+暴力去枚举即可.

#include<stdio.h>
#include<string.h>

const int maxn = 107;
const int oo = 1e9+7;

char s[maxn][maxn];
int f[maxn];

void getFail(char *P)
{
    int m = strlen(P);
    f[0] = f[1] = 0;
    for(int i = 1; i < m; i++)//虽然字符串是0到m-1,但是要求出f[m]的值
    {
        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 *T, char *P) //找到所有匹配点
{
    int n = strlen(T);
    int m = strlen(P);
    int j = 0;
    for(int i = 0; i < n; i++)
    {
        while(j && T[i] != P[j]) j = f[j];
        if(T[i] == P[j]) j++;
        if(j == m) return true;//就算j到m了,也用f[m]继续匹配
    }
    return false;
}
int main()
{
    int T;

    scanf("%d", &T);

    while(T--)
    {
        int i, j, len, M, MaxLen=60;
        char ans[maxn] = "Z";

        scanf("%d", &M);

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

        for(len=60; len>=3; len--)
        for(i=0; i<=MaxLen-len; i++)
        {///枚举第一个串的所有子串
            char b[maxn]={0};

            strncpy(b, s[0]+i, len);
            getFail(b);

            for(j=1; j<M; j++)
            {
                if(find(s[j], b) == false)
                    break;
            }

            if(j==M && strcmp(ans, b) > 0)
                strcpy(ans, b);

            if(ans[0] != 'Z' && i==MaxLen-len)
                i=100, len = 0;///跳出循环
        }

        if(ans[0] == 'Z')
            printf("no significant commonalities\n");
        else
            printf("%s\n", ans);
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/sgh666666/article/details/82425478
今日推荐