POJ 3080 Blue Jeans(KMP + 暴力)

一开始感觉好难啊,除了暴力枚举我想不到其他办法。
然后就去看看别人的思路,发现竟然可以用暴力写!

我也没什么好顾虑的,然后就闷着头去写了。枚举样例第一个DNA串的所有长度大于3的子串,然后用这些和除了第一个DNA串KMP匹配即可。

遇到长的就替换一下,遇到长度相等的取字典序最小的继续替换…没什么弯。
我觉得难点吧,就是枚举所有子串那一部分,那个地方我写的很晕,在加上暴力的代码又那么长,越写越浑。最后把那一块单拉出来写的,最后清楚了。

先附上那一块的代码(枚举长度所有大于3的子串)

#include <iostream>
#include <cstring>

using namespace std;

char s[60];
char t[60];

int main()
{

    cin >> s;
    int len1 = strlen(s);
    for(int i = 3; i<= len1; i++)
    {
        for(int j = 0; j < len1; ++j)
        {
            int len2 = 0;
            for(int k = j;; k++)
            {
                t[len2++] = s[k];
                if(len2 == i)
                    break;
            }
            t[len2] = '\0';
            cout << t << endl;
        }
    }
    return 0;
}

在这里插入图片描述
这个代码虽然把想要的子串全枚举了,但不符合要求的同样也列出来了(长度小于3的),
这样就会增加时间的复杂度(而且还不少)、、可以剪枝一下。
不过还好啦,我没剪枝最后输出的时候判断答案串长度大于等于3就行,也ac了。如果有强迫症的同学,可以在枚举子串的时候优化一下…
然后把kmp匹配嵌套进去就ok

下面是代码,代码有点长。不过暴力代码一般都这样,没办法,而且我写的可能有点臃肿,但我的思路我觉得还是清晰,就是读起来的时候乱七八糟的变量名可能让人费解…
不过咬牙看也能理解鸭!

#include <iostream>
#include <cstring>
#include <cstdio>

using namespace std;

char DNA[11][66], dna[66], ans[66];
int Next[66];
int len1, len2;
bool flag;

void getNext(char *dna)
{
    int j = 0, t = -1;
    Next[0] = -1;
    while(j < len2)
    {
        if(t == -1 || dna[j] == dna[t])
        {
            t++;
            j++;
            Next[j] = t;
        }
        else
            t = Next[t];
    }
    return;
}

bool KMP(char *DNA, char *dna)
{

    int i = 0, j = 0;
    while(i < len1 && j < len2)
    {
        if(j == -1 || DNA[i] == dna[j])
        {
            i++;
            j++;
        }
        else
            j = Next[j];
    }
    if(j >= len2)
        return true;
    else
        return false;
}

int main()
{

    int test;
    cin >> test;
    while(test--){

    int n;
    cin >> n;
    for(int i = 0; i < n; ++i)
    {
        scanf("%s",DNA[i]);
    }
    int len_0 = strlen(DNA[0]);//len_0表示第一个串的长度
    for(int i = 3; i <= len_0; ++i)//子串从3开始,最大的长度为len_0
    {
        for(int j = 0; DNA[0][j] != '\0'; ++j)
        {

            int len  = 0;
            for(int k = j;; k++)
            {
                dna[len++] = DNA[0][k];
                if(len == i)
                    break;
            }
            dna[len] = '\0';//以上是列举子串

            len2 = strlen(dna);//子串长度
            getNext(dna);
            for(int j = 1; j < n; ++j)
            {
                len1 = strlen(DNA[j]);//要匹配的主串长度
                flag = KMP(DNA[j],dna);
                if(!flag)
                    break;
                else
                    continue;
            }
            if(flag)
            {
                int c = strlen(ans);//答案串的长度。
                //所以一开始答案串的长度为0,我在下面初始化了
                if(c < len2)
                    strcpy(ans,dna);//留长的
                if(c == len2)
                {
                    if(strcmp(dna,ans)<0)
                        strcpy(ans,dna);//留小的
                }
            }
        }

    }

    if(strlen(ans)>=3)//输出长度大于等于3的答案串
        cout << ans << endl;
    else
        cout << "no significant commonalities" << endl;
        memset(ans,0,sizeof(ans));//放在这儿初始化了,因为发现错了才临时加的,放前面比较好
     }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44031744/article/details/86720736