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
原文地址:https://www.cnblogs.com/shutdown113/p/9418054.html