zoukankan      html  css  js  c++  java
  • 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;
    }
    


  • 相关阅读:
    太鼓达人
    DB2中循环日期跑数据
    DB2分区表删除和添加分区
    DB2日常运维之总结(转)
    oracle SQL not in null,单列,复合列
    利用rlwrap配置linux下oracle sqlplus 历史记录回调
    Oracle非默认监听的处理会遇到的问题以及处理方法
    Sqlserver循环嵌套
    rman全备份异机恢复
    Windows系统下Oracle数据库冷备
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/6777448.html
Copyright © 2011-2022 走看看