POJ3450【KMP理解】

题意:
求多个字符串的最长公共子串
思路:
4000个串,200长度。
一种暴力,对于一个串最多有200*200=40000级别个子串,然后我要再处理一下next数组200,8e6复杂度;
然后我要和4000个串去匹配一下,看看符不符合,400000*4000*200这样就炸了;

其实显然不需要所有的子串都枚举出来,可以二分来搞,因为显然如果有aaaa为最长公共字串,则aaa则一定有。


然后参考了一篇博文,用KMP,是利用其快速求最长前缀,所以只需要枚举开头即最多200/2=100次。复杂度才O(4000*100)
这份代码的GetlongestPre函数中,逐渐缩短模式串也有贪心的意思。
看自己理解吧。


//#include<bits/stdc++.h>
//using namespace std;
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;

const int N=4e3+10;
const int M=2e2+10;

char wxy[N][M];
int next[M],n;

void GetNext(char *s,int len)
{
    int i,j;
    next[0]=-1;
    i=0;
    j=-1;
    while(i<len)
    {
        if(j==-1||s[i]==s[j])
            next[++i]=++j;
        else
            j=next[j];
    }
}

int GetLongestPre(char *s,int len)
{
    GetNext(s,len);
    for(int i=1; i<n; i++)
    {
        char *p=wxy[i];
        int j=0,tmp=0;
        while(*p&&j<len)
        {
            if(j==-1||*p==s[j])
            {
                p++;
                j++;
                tmp=max(tmp,j);
            }
            else
                j=next[j];
        }
        len=tmp;
    }
    return len;
}

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

        int len=strlen(wxy[0]);
        int ans=0,biginpos=0;
        for(int i=0; i<len; i++)
        {
            int tmp=GetLongestPre(wxy[0]+i,len-i);
            if(tmp>=ans)
            {
                if(tmp>ans)
                {
                    ans=tmp;
                    biginpos=i;
                }
                else
                {
                    bool flag=true;
                    for(int t=0; t<ans; t++)
                    {
                        if(wxy[0][biginpos+t] > wxy[0][i+t]) break;
                        else if(wxy[0][biginpos+t] < wxy[0][i+t])
                        {
                            flag=false;
                            break;
                        }
                    }
                    if(flag)
                        biginpos=i;
                }
            }
        }
        if(ans)
            for(int i=0; i<ans; i++)
                printf("%c",wxy[0][biginpos+i]);
        else
            printf("IDENTITY LOST");
        puts("");
    }
    return 0;
}


原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777448.html