zoukankan      html  css  js  c++  java
  • POJ 2774 后缀数组:查找最长公共子

    思考:其实很easy。就在两个串在一起。通过一个特殊字符,中间分隔,然后找到后缀数组的最长的公共前缀。然后在两个不同的串,最长是最长的公共子串。

    注意的是:用第一个字符串来推断是不是在同一个字符中,刚開始用了第二个字符的长度来推断WA了2发才发现。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<queue>
    #include<set>
    #include<cmath>
    #include<bitset>
    #define mem(a,b) memset(a,b,sizeof(a))
    #define lson i<<1,l,mid
    #define rson i<<1|1,mid+1,r
    #define llson j<<1,l,mid
    #define rrson j<<1|1,mid+1,r
    #define INF 0x7fffffff
    #define maxn 200010
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    void radix(int *str,int *a,int *b,int n,int m)
    {
        static int count[maxn];
        mem(count,0);
        for(int i=0; i<n; i++) ++count[str[a[i]]];
        for(int i=1; i<=m; i++) count[i]+=count[i-1];
        for(int i=n-1; i>=0; i--) b[--count[str[a[i]]]]=a[i];
    }
    void suffix(int *str,int *sa,int n,int m) //倍增算法计算出后缀数组sa
    {
        static int rank[maxn],a[maxn],b[maxn];
        for(int i=0; i<n; i++) rank[i]=i;
        radix(str,rank,sa,n,m);
        rank[sa[0]]=0;
        for(int i=1; i<n; i++)
            rank[sa[i]]=rank[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]);
        for(int i=0; 1<<i<n; i++)
        {
            for(int j=0; j<n; j++)
            {
                a[j]=rank[j]+1;
                b[j]=j+(1<<i)>=n?0:rank[j+(1<<i)]+1;
                sa[j]=j;
            }
            radix(b,sa,rank,n,n);
            radix(a,rank,sa,n,n);
            rank[sa[0]]=0;
            for(int j=1; j<n; j++)
                rank[sa[j]]=rank[sa[j-1]]+(a[sa[j-1]]!=a[sa[j]]||b[sa[j-1]]!=b[sa[j]]);
        }
    }
    void calcHeight(int *str,int *sa,int *h,int *rank,int n) //求出最长公共前缀数组h
    {
        int k=0;
        h[0]=0;
        for(int i=0; i<n; i++) rank[sa[i]]=i;
        for(int i=0; i<n; i++)
        {
            k=k==0?0:k-1;
            if(rank[i])
                while(str[i+k]==str[sa[rank[i]-1]+k]) k++;
            else k=0;
            h[rank[i]]=k;
        }
    }
    int a[maxn],sa[maxn],height[maxn],rank[maxn];
    string s,ss;
    int main()
    {
        //freopen("1.txt","r",stdin);
        while(cin>>s>>ss)
        {
            ss=s+"#"+ss;
            copy(ss.begin(),ss.end(),a);
            int n=ss.size(),len=0;
            suffix(a,sa,n,256);
            calcHeight(a,sa,height,rank,n);
            for(int i=1; i<n; i++)
                if(height[i]>len&&((sa[i]<s.size())!=sa[i-1]<s.size()))
                    len=height[i];
            cout<<len<<endl;
        }
        return 0;
    }
    /*
    jworerrrrr
    rrreeeeeeeee
    abcd
    stedste
    */
    


    版权声明:本文博主原创文章,博客,未经同意不得转载。

  • 相关阅读:
    Android在onCreate()中获得控件尺寸
    Java根据出生年月日获取到当前日期的年月日
    Oracle 取随机数
    filter,orderBy等过滤器
    ng-repeat 指令
    三元表达式、逻辑表达式 与 &&、||的妙用
    ng-switch 指令
    sublime text 3.0 安装 HTML-CSS-JS Prettify
    JS相关环境搭建:Nodejs、karma测试框架、jsDuck、Express
    关于VSS上的项目源码管理的注意问题
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4813598.html
Copyright © 2011-2022 走看看