zoukankan      html  css  js  c++  java
  • poj2774(后缀树组)

    Long Long Message

    题意:

      求两个字符串的最长连续公共子串。

    分析:

      后缀树组的模板题。首先明确一点,这个最长连续公共子串s一定是这两个字符串中的某个字符的后缀的最长公共前缀(假设s首字母在两个字符串中的对应位置为i,j,那么i,j后缀的最长公共前缀就是s)。那么当我们将这两个字符串拼接在一起后,求得任意两个字符(位于不同字符串)的后缀的最长公共前缀中的最优解即是答案。而求后缀的最长公共前缀就是求后缀数组中height数组,所以我们只需要算出height数组后,判断对应的两个字符是否位于不同字符串即可。

    代码:

    倍增算法

    #include <map>
    #include <queue>
    #include <math.h>
    #include <string>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define cls(x) memset(x,0,sizeof(x))
    #define clslow(x) memset(x,-1,sizeof(x))
    
    const int maxn=2e6+100;
    
    int s[maxn];
    char str1[maxn],str2[maxn];
    int sa[maxn],height[maxn],Rank[maxn];
    
    namespace Suffix {
        int wa[maxn],wb[maxn],wv[maxn],wt[maxn];
        int cmp(int *r,int a,int b,int k)
        {
            return r[a]==r[b]&&r[a+k]==r[b+k];
        }
        void da(int *r,int *sa,int n,int m)
        {
            int i,j,p,*x=wa,*y=wb,*t;
            for(i=0; i<m; i++)  wt[i]=0;
            for(i=0; i<=n; i++)  wt[x[i]=r[i]]++;
            for(i=1; i<m; i++)  wt[i]+=wt[i-1];
            for(i=n; i>=0; i--)  sa[--wt[x[i]]]=i;
            p=1;
            j=1;
            for(; p<=n; j*=2,m=p)
            {
                for(p=0,i=n+1-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<=n; i++)  wv[i]=x[y[i]];
                for(i=0; i<m; i++)  wt[i]=0;
                for(i=0; i<=n; i++)  wt[wv[i]]++;
                for(i=1; i<m; i++)  wt[i]+=wt[i-1];
                for(i=n; i>=0; i--)  sa[--wt[wv[i]]]=y[i];
                t=x;
                x=y;
                y=t;
                x[sa[0]]=0;
                for(p=1,i=1; i<=n; i++)
                    x[sa[i]]=cmp(y,sa[i-1],sa[i],j)? p-1:p++;
            }
        }
        void getheight(int *r,int* sa,int n)
        {
            int i,j,k=0;
            for(i=1; i<=n; i++)  Rank[sa[i]]=i;
            for(i=0; i<n; i++)
            {
                if(k)
                    k--;
                else
                    k=0;
                j=sa[Rank[i]-1];
                while(r[i+k]==r[j+k])
                    k++;
                height[Rank[i]-1]=k;
            }
        }
    };
    
    int main()
    {
    //    freopen("in.txt","r",stdin);
        while(scanf("%s%s",str1,str2)!=EOF)
        {
            int len1=strlen(str1);
            int len2=strlen(str2);
            for(int i=0;i<len1;i++){
                s[i]=str1[i]-'a'+1;
            }
            s[len1]=30;
            for(int i=0;i<len2;i++){
                s[i+len1+1]=str2[i]-'a'+1;
            }
            s[len1+len2+1]=0;
            int sz=len1+len2+1;
            Suffix::da(s,sa,sz,31);
            Suffix::getheight(s,sa,sz);
    
            int maxlen=0;
            for(int i=2;i<sz;i++){
                if(height[i-1]>maxlen){
                    if((ll)(sa[i-1]-len1)*(sa[i]-len1)<0){
                        maxlen=height[i-1];
                    }
                }
            }
            printf("%d
    ",maxlen);
        }
        return 0;
    }
    View Code

    dc3算法

    #include <map>
    #include <queue>
    #include <math.h>
    #include <string>
    #include <stdio.h>
    #include <string.h>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    #define ll long long
    #define ull unsigned long long
    #define cls(x) memset(x,0,sizeof(x))
    #define clslow(x) memset(x,-1,sizeof(x))
    
    const int maxn=2e6+100;
    
    int s[maxn];
    char str1[maxn],str2[maxn];
    int sa[maxn],height[maxn],Rank[maxn];
    
    namespace Suffix {
        int wa[maxn],wb[maxn],wv[maxn],wt[maxn];
        #define F(x) ((x)/3+((x)%3==1?0:tb))
        #define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
        int c0(int r[], int a, int b)
        {
            return r[a]==r[b] && r[a+1]==r[b+1] && r[a+2]==r[b+2];
        }
        int c12(int k, int r[], int a, int b)
        {
            if(k==2)    return r[a]<r[b] || (r[a]==r[b] && c12(1,r,a+1,b+1));
            else        return r[a]<r[b] || (r[a]==r[b] && wv[a+1]<wv[b+1]);
        }
        void Rsort(int r[], int a[], int b[], int n, int m){
            int i;
            for(i = 0; i < n; ++i)  wv[i] = r[a[i]];
            for(i = 0; i < m; ++i)  wt[i] = 0;
            for(i = 0; i < n; ++i)  ++wt[wv[i]];
            for(i = 1; i < m; ++i)  wt[i] += wt[i-1];
            for(i = n-1; i >= 0; --i)  b[--wt[wv[i]]] = a[i];
        }
        void dc3(int r[], int sa[], int n, int m){
            int i, j, *rn = r+n, *san = sa+n, ta=0, tb=(n+1)/3, tbc=0, p;
            r[n] = r[n+1] = 0;
            for(i = 0; i < n; ++i)
                if(i%3!=0)  wa[tbc++] = i;
            Rsort(r+2, wa, wb, tbc, m);
            Rsort(r+1, wb, wa, tbc, m);
            Rsort(r, wa, wb, tbc, m);
            rn[F(wb[0])] = 0;  p = 1;
            for(i = 1; i < tbc ; ++i)   rn[F(wb[i])] = c0(r, wb[i-1], wb[i]) ? p-1 : p++;
            if(p < tbc)
                dc3(rn, san, tbc, p);
            else
                for(i=0;i<tbc;i++)
                    san[rn[i]] = i;
            for(i = 0; i < tbc; ++i)
                if(san[i]<tb)
                    wb[ta++] = san[i]*3;
            if(n%3==1)
                wb[ta++]=n-1;
            Rsort(r, wb, wa, ta, m);
            for(i = 0; i < tbc; ++i)
                wv[wb[i] = G(san[i])] = i;
            for(i=0,j=0,p=0; i<ta && j<tbc; p++)
                sa[p] = c12(wb[j]%3, r, wa[i], wb[j]) ? wa[i++] : wb[j++];
            while(i < ta)
                sa[p++] = wa[i++];
            while(j < tbc)
                sa[p++] = wb[j++];
        }
        void getheight(int *r,int* sa,int n)
        {
            int i,j,k=0;
            for(i=1; i<=n; i++)  Rank[sa[i]]=i;
            for(i=0; i<n; i++)
            {
                if(k)
                    k--;
                else
                    k=0;
                j=sa[Rank[i]-1];
                while(r[i+k]==r[j+k])
                    k++;
                height[Rank[i]-1]=k;
            }
        }
    };
    
    int main()
    {
    //    freopen("in.txt","r",stdin);
        while(scanf("%s%s",str1,str2)!=EOF)
        {
            int len1=strlen(str1);
            int len2=strlen(str2);
            for(int i=0;i<len1;i++){
                s[i]=str1[i]-'a'+1;
            }
            s[len1]=30;
            for(int i=0;i<len2;i++){
                s[i+len1+1]=str2[i]-'a'+1;
            }
            s[len1+len2+1]=0;
            int sz=len1+len2+1;
            Suffix::dc3(s,sa,sz+1,31);
            Suffix::getheight(s,sa,sz);
    
            int maxlen=0;
            for(int i=2;i<sz;i++){
                if(height[i-1]>maxlen){
                    if((ll)(sa[i-1]-len1)*(sa[i]-len1)<0){
                        maxlen=height[i-1];
                    }
                }
            }
            printf("%d
    ",maxlen);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Tensorflow 2.0 学习资源
    SpagoBI 教程 Lesson 5: Creating a dashboard with BIRT and SpagoBI
    SpagoBI 教程 Lesson 4: BIRT Reports
    SpagoBI 教程 Lesson 3: Highchart Dashboards
    SpagoBI 教程 Lesson 2: OLAP with JPIVOT
    SpagoBI 教程 Lesson 1:Introduction and Installation
    Oracle system表空间满的暂定解决方法
    运算符重载_继承_多态_模版
    成员函数返回的是对象和引用的区别(转)
    String类型_static成员_动态内存分配_拷贝构造函数_const关键字_友元函数与友元类
  • 原文地址:https://www.cnblogs.com/shutdown113/p/9418054.html
Copyright © 2011-2022 走看看