POJ - 3080 Blue Jeans 【KMP+暴力】(最大公共字串)

<题目链接>

题目大意:

就是求k个长度为60的字符串的最长连续公共子串,2<=k<=10

限制条件:

1、  最长公共串长度小于3输出   no significant commonalities

2、  若出现等长的最长的子串,则输出字典序最小的串

解题分析:

将第一个字串的所有子串枚举出来,然后用KMP快速判断该子串是否在所有主串中出现,如果都出现过,那么就按该子串的长度和字典序,不断更新答案,直到得到最终的最优解。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
using namespace std;

const int maxn = 1100;

char a[maxn];
char b[maxn];
int next0[maxn];
char s[15][maxn];

void find_next()
{
    int len = strlen(b);
    int k = -1;
    next0[0] = -1;
    int j = 0;
    while (j < len - 1)
    {
        if (k == -1 || b[j] == b[k])
        {
            next0[++j] = ++k;
        }
        else
            k = next0[k];
    }
}

int kmp()
{
    int i = 0, j = 0;
    int alen = strlen(a);
    int blen = strlen(b);
    while (i < alen&&j < blen)
    {
        if (j == -1 || a[i] == b[j])
        {
            i++;
            j++;
        }
        else
            j = next0[j];
    }
    if (j == blen)return i - j + 1;        
    return -1;
}


int main()
{
    int t; scanf("%d", &t);
    while (t--)
    {
        int n; scanf("%d", &n);
        getchar();
        for (int i = 0; i < n; i++)
        {
            scanf("%s", &s[i]);
        }

        int len = strlen(s[0]);
        int cnt = 0;
        char ans[maxn];
        for (int i = 0; i < len; i++)
        {
            for (int j = 1; j <= len - i; j++)
            {
                for (int k = 0; k < j; k++)
                    b[k] = s[0][i + k];
                b[j] = '\0';
                find_next();
                bool flag = true;
                for (int k = 1; k < n; k++)
                {
                    strcpy(a, s[k]);
                    if (kmp() == -1)
                    {
                        flag = false;
                        break;
                    }
                }
                if (flag)        //如果该子串为所有主串的公共子串
                {
                    int lenng = strlen(b);
                    if (j > cnt&&lenng >= 3)    //cnt为最长公共子串的长度
                    {
                        cnt = j;
                        strcpy(ans, b);          //ans储存的是最终符合要求的最长公共子串
                    }
                    if (j == cnt && strcmp(ans, b) > 0)strcpy(ans, b);
                    //按字典序更新与当前最长公共子串长度相同的公共子串
                }
            }
        }
        if (cnt == 0)printf("no significant commonalities\n");
        else
            printf("%s\n", ans);
    }
    return 0;
}

2018-08-07

猜你喜欢

转载自www.cnblogs.com/00isok/p/9439897.html