POJ 2774 Long Long Message 题解&代码

第二道后缀数组…其实感觉比上一道简单【23333
后缀数组的主要用法之一就是height[]…

这道题就是把两个字符串用分隔符连接起来,求新字符串的height[],然后找到有效height的最大值即可【有效height就是该height对应的两个串分别在两个字符串中

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=100005*2;
const int maxm=maxn;
char str[maxn];
int l1,l2,ans;
int num[maxn],sa[maxn],rank[maxn],height[maxn];
int wa[maxn],wb[maxn],wv[maxn],cnt[maxm];
void DA(int *r,int n,int m)
{
    int *x=wa,*y=wb,p;
    for(int i=0;i<m;i++)cnt[i]=0;
    for(int i=0;i<n;i++)cnt[x[i]=r[i]]++;
    for(int i=1;i<m;i++)cnt[i]+=cnt[i-1];
    for(int i=n-1;i>=0;i--)sa[--cnt[x[i]]]=i;
    for(int j=1;j<n;j<<=1)
    {
        p=0;
        for(int i=n-j;i<n;i++)y[p++]=i;
        for(int i=0;i<n;i++)if(sa[i]-j>=0)y[p++]=sa[i]-j;
        for(int i=0;i<n;i++)wv[i]=x[y[i]];
        for(int i=0;i<m;i++)cnt[i]=0;
        for(int i=0;i<n;i++)cnt[wv[i]]++;
        for(int i=1;i<m;i++)cnt[i]+=cnt[i-1];
        for(int i=n-1;i>=0;i--)sa[--cnt[wv[i]]]=y[i];
        swap(x,y);
        p=1;x[sa[0]]=0;
        for(int i=1;i<n;i++)
            x[sa[i]]=(y[sa[i]]==y[sa[i-1]] && y[sa[i]+j]==y[sa[i-1]+j])?p-1:p++;
        if(p>=n)break;
        m=p;
    }
    for(int i=1;i<n;i++)
        rank[sa[i]]=i;
}
void calheight(int *r,int n)
{
    int j=0,k=0;
    for(int i=0;i<n;height[rank[i]]=k,i++)
        for(k?k--:k=0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
}
int main(void)
{
    scanf("%s",str);
    l1=strlen(str);
    for(int i=0;i<l1;i++)
        num[i]=str[i]-'a'+2;
    num[l1]=1;
    scanf("%s",str);
    l2=strlen(str);
    for(int i=0;i<l2;i++)
        num[l1+i+1]=str[i]-'a'+2;
    l2+=l1+1;
    DA(num,l2+1,30);
    calheight(num,l2);
    for(int i=2;i<l2;i++)
        if((sa[i]<l1 && sa[i-1]>l1) || (sa[i]>l1 && sa[i-1]<l1))
            ans=max(ans,height[i]);
    printf("%d\n",ans);
    return 0;
}

你可能感兴趣的:(poj)