zoukankan      html  css  js  c++  java
  • 【后缀数组】【poj2774】【 Long Long Message】

    题意:

    求两个串的最长连续子串。


    我的想法:

          枚举第二个串...在第一个串的后缀数组中二分查找.

          复杂度NlogN。最坏情况N^2


    题解:

    (3)height 数组:定义height[i]=suffix(SA[i-1])和suffix(SA[i])的最长公共前缀,也就是排名相邻的两个后缀的最长公共前缀。

    (4) h[i]=height[rank[i]],也就是suffix(i)和在它前一名的后缀的最长公共前缀。

    (5)LCP(i,j):对正整数i,j 定义LCP(i,j)=lcp(Suffix(SA[i]),Suffix(SA[j]),其中i,j 均为1 至n 的整数。LCP(i,j)也就是后缀数组中第i 个和第j 个后缀的最长公共前缀的长度。其中,函数lcp(u,v)=max{i|u=v},也就是从头开始顺次比较u 和v 的对应字符,对应字符持续相等的最大位置,称为这两个字符串的最长公共前缀。

    2.2   几个性质

    (1)LCP(i,j)=min{height[k]|i+1≤k≤j},也就是说,计算LCP(i,j)等同于询问一维数组height 中下标在i+1 到j 范围内的所有元素的最小值。

       

    (1) 最长公共子串。给定两个字符串A 和B,求最长公共子串。

    『解析』先将第二个字符串写在第一个字符串后面,中间用一个没有出现过的字符隔开,再求这个新的字符串的后缀数组。当suffix(sa[i-1]) 和suffix(sa[i])不是同一个字符串中的两个后缀时,max{height[i]}才是满足条件


    ..代码 二段 有一种WA了1万次才过
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <string>
    #define oo 0x13131313
    using namespace std;
        /*
        *suffix array
        *倍增算法  O(n*logn)
        *待排序数组长度为n,放在0~n-1中,在最后面补一个0
        *build_sa( ,n+1, );//注意是n+1;
        *getHeight(,n);
        *例如:
        *n   = 8;
        *num[]   = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0,其他大于0
        *rank[]  = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值,rank[n]必定为0无效值
        *sa[]    = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值,sa[0]必定为n是无效值
        *height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值
        *
        */
    const int MAXN=300000+5;
    char S1[MAXN],S2[MAXN];
    int sa[MAXN];
    int t1[MAXN],t2[MAXN],c[MAXN];
    int rank[MAXN],height[MAXN];
    void build_sa(int s[],int n ,int m)
    {
        int i,j,p,*x=t1,*y=t2;
        for(int i=0;i<m;i++) c[i]=0;
        for(int i=0;i<n;i++) c[x[i]=s[i]]++;
        for(int i=0;i<m;i++) c[i]+=c[i-1];
        for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
        for(j=1;j<=n;j<<=1)
        {
            p=0;
            for(i=n-j;i<n;i++) y[p++]=i;
            for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
            for(i=0;i<m;i++) c[i]=0;
            for(i=0;i<n;i++) c[x[y[i]]]++;
            for(i=0;i<m;i++) c[i]+=c[i-1];
            for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
            swap(x,y);
            p=1;x[sa[0]]=0;
            for(i=1;i<n;i++)
                x[sa[i]]=(y[sa[i-1]]==y[sa[i]])&&(y[sa[i-1]+j]==y[sa[i]+j])?p-1:p++;
            if(p>=n) break;
            m=p;
        }
    }
    int s[MAXN];
    int len1,len2,ans=0;
    void getHeight(int s[],int n)
    {
        int i,j,k=0;
        for(i=0;i<=n;i++)rank[sa[i]]=i;
        for(i=0;i<n;i++)
        {
            if(k)k--;
            j=sa[rank[i]-1];
            while(s[i+k]==s[j+k])k++;
            height[rank[i]]=k;
        }
    }
    int main()
    {
       // freopen("a.in","r",stdin);
       // freopen("a.out","w",stdout);
    	while(scanf("%s",S1)!=EOF)
        {
            int ans=0;
            len1=strlen(S1);
            scanf("%s",S2);
            len2=strlen(S2);
            for(int i=0;i<len1;i++) s[i]=S1[i];
            s[len1]='$';
            for(int i=len1+1;i<=len2+len1+1;i++) s[i]=S2[i-len1-1];
            build_sa(s,len1+len2+2,256);
            getHeight(s,len1+len2+1);
            for(int i=2;i<=len1+len2+1;i++)
            {
                int MAX=max(sa[i-1],sa[i]);
                int MIN=min(sa[i-1],sa[i]);
                if(MAX>len1&&MIN<len1)
                {
                    if(ans<height[i])
                        ans=height[i];
                }
            }
            cout<<ans<<endl;
        }
    }
    

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <cstring>
    #include <ctime>
    #include <algorithm>
    #include <iostream>
    #include <sstream>
    #include <string>
    #define oo 0x13131313
    using namespace std;
        /*
        *suffix array
        *倍增算法  O(n*logn)
        *待排序数组长度为n,放在0~n-1中,在最后面补一个0
        *build_sa( ,n+1, );//注意是n+1;
        *getHeight(,n);
        *例如:
        *n   = 8;
        *num[]   = { 1, 1, 2, 1, 1, 1, 1, 2, $ };注意num最后一位为0,其他大于0
        *rank[]  = { 4, 6, 8, 1, 2, 3, 5, 7, 0 };rank[0~n-1]为有效值,rank[n]必定为0无效值
        *sa[]    = { 8, 3, 4, 5, 0, 6, 1, 7, 2 };sa[1~n]为有效值,sa[0]必定为n是无效值
        *height[]= { 0, 0, 3, 2, 3, 1, 2, 0, 1 };height[2~n]为有效值
        *
        */
    const int MAXN=300000+5;
    char S1[MAXN],S2[MAXN];
    int sa[MAXN];
    int t1[MAXN],t2[MAXN],c[MAXN];
    int rank[MAXN],height[MAXN];
    void build_sa(int s[],int n ,int m)
    {
        int i,j,p,*x=t1,*y=t2;
        for(int i=0;i<m;i++) c[i]=0;
        for(int i=0;i<n;i++) c[x[i]=s[i]]++;
        for(int i=0;i<m;i++) c[i]+=c[i-1];
        for(int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;
        for(j=1;j<=n;j<<=1)
        {
            p=0;
            for(i=n-j;i<n;i++) y[p++]=i;
            for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
            for(i=0;i<m;i++) c[i]=0;
            for(i=0;i<n;i++) c[x[y[i]]]++;
            for(i=0;i<m;i++) c[i]+=c[i-1];
            for(i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];
            swap(x,y);
            p=1;x[sa[0]]=0;
            for(i=1;i<n;i++)
                x[sa[i]]=(y[sa[i-1]]==y[sa[i]])&&(y[sa[i-1]+j]==y[sa[i]+j])?p-1:p++;
            if(p>=n) break;
            m=p;
        }
    }
    int s[MAXN];
    int len1,len2,ans=0;
    void getHeight(int s[],int n)
    {
        int i,j,k=0;
        for(i=0;i<=n;i++)rank[sa[i]]=i;
        for(i=0;i<n;i++)
        {
            if(k)k--;
            j=sa[rank[i]-1];
            while(s[i+k]==s[j+k])k++;
            height[rank[i]]=k;
        }
    }
    int main()
    {
        //freopen("a.in","r",stdin);
        //freopen("a.out","w",stdout);
    	while(scanf("%s",S1)!=EOF)
        {
            int ans=0;
            len1=strlen(S1);
            scanf("%s",S2);
            len2=strlen(S2);
            for(int i=0;i<len1;i++) s[i]=S1[i];
            s[len1]='@';
            for(int i=len1+1;i<=len2+len1+1;i++) s[i]=S2[i-len1-1];
            build_sa(s,len1+len2+2,128);
            getHeight(s,len1+len2+1);
            for(int i=2;i<=len1+len2+1;i++)
            {
                if((long long)(sa[i]-len1)*(long long)(sa[i-1]-len1)<0)     //乘爆了long long WA了无数发 真是酸爽
                {
                    if(ans<height[i])
                        ans=height[i];
                }
            }
            cout<<ans<<endl;
        }
    }
    



  • 相关阅读:
    SharePoint Framework (SPFx) 开发入门教程
    SharePoint 2013 Designer 入门教程
    SharePoint 2013 开发教程
    SharePoint 2013 入门教程
    SharePoint Online 部署SPFx Web部件
    SharePoint Online SPFx Web部件绑定数据
    SharePoint Online 创建SPFx客户端Web部件
    SharePoint Online 配置框架(SPFx)开发环境
    SharePoint Online 创建应用程序目录
    SharePoint Online 启用 IRM
  • 原文地址:https://www.cnblogs.com/zy691357966/p/5480325.html
Copyright © 2011-2022 走看看