• POJ 2774 Long Long Message(后缀数组)


    【题目链接】 http://poj.org/problem?id=2774

    【题目大意】

      求最长公共子串

    【题解】

      将两个串中间嵌一个字符相连,求一遍后缀数组
      如果排名相邻的两个后缀的开端是分属于两个串的,
      那么他们的最长公共前缀就可以用来更新答案

    【代码】

    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int N=4000010;
    int n,rank[N],sa[N],h[N],tmp[N],cnt[N],ans;char s[N];
    void suffixarray(int n,int m){
        int i,j,k;n++;
        for(i=0;i<2*n+5;i++)rank[i]=sa[i]=h[i]=tmp[i]=0;
        for(i=0;i<m;i++)cnt[i]=0;
        for(i=0;i<n;i++)cnt[rank[i]=s[i]]++;
        for(i=1;i<m;i++)cnt[i]+=cnt[i-1];
        for(i=0;i<n;i++)sa[--cnt[rank[i]]]=i;
        for(k=1;k<=n;k<<=1){
            for(i=0;i<n;i++){
                j=sa[i]-k;
                if(j<0)j+=n;
                tmp[cnt[rank[j]]++]=j;
            }sa[tmp[cnt[0]=0]]=j=0;
            for(i=1;i<n;i++){
                if(rank[tmp[i]]!=rank[tmp[i-1]]||rank[tmp[i]+k]!=rank[tmp[i-1]+k])cnt[++j]=i;
                sa[tmp[i]]=j;
            }memcpy(rank,sa,n*sizeof(int));
            memcpy(sa,tmp,n*sizeof(int));
            if(j>=n-1)break;
        }for(j=rank[h[i=k=0]=0];i<n-1;i++,k++)
        while(~k&&s[i]!=s[sa[j-1]+k])h[j]=k--,j=rank[sa[j]+1];
    }
    int main(){
        while(~scanf("%s",s)){
            int len=strlen(s); s[len]='#';
            scanf("%s",s+len+1);
            n=strlen(s);
            suffixarray(n,256); ans=0;
            for(int i=2;i<n;i++){
                if(ans<h[i]){
                    if(sa[i]>len&&sa[i-1]<len||sa[i]<len&&sa[i-1]>len)ans=h[i];
                }
            }printf("%d
    ",ans);
        }return 0;
    }
    

      

  • 相关阅读:
    如何优雅地结束线程的生命周期
    线程的interrupt()
    线程的join()方法
    守护线程Daemon
    使用多线程模拟一个银行叫号窗口
    多线程介绍
    十八、MySQL 数据排名查询某条数据是总数据的第几条
    spring cloud stream整合
    036线程进程(重要)
    035server端并发聊天
  • 原文地址:https://www.cnblogs.com/forever97/p/poj2774.html
Copyright © 2020-2023  润新知