【POJ2774】Long Long Message,第一次的后缀数组

Time:2016.05.21
Author:xiaoyimi
转载注明出处谢谢


传送门
思路:没什么值得说的,大家想看思路的话还是去看大牛们的吧,磨了将近一天的后缀数组,基本按照模板打得,最后发现有些bug,又去博采众长才艰难的A掉,WA了不知道多少次啊啊啊
注意:
使用指针交换数组元素是很快的 ——by Yveh
代码:

#include<cstdio>
#include<iostream>
#define M 200004
using namespace std;
int cnt[M],w[M],sa[M],rank[M],height[M],tmp[M];
void SA(int len,int up)
{
    int *rk=rank,p=0,*id=height,*t=tmp,d=1;
    for (int i=0;i<up;i++) cnt[i]=0;
    for (int i=0;i<len;i++) cnt[rk[i]=w[i]]++;
    for (int i=1;i<up;i++) cnt[i]+=cnt[i-1];
    for (int i=len-1;i>=0;i--) sa[--cnt[rk[i]]]=i;
    for (;;)
    {
        for (int i=len-d;i<len;i++) id[p++]=i;
        for (int i=0;i<len;i++)
            if (sa[i]>=d) id[p++]=sa[i]-d;
        for (int i=0;i<up;i++) cnt[i]=0;
        for (int i=0;i<len;i++) cnt[t[i]=rk[id[i]]]++;
        for (int i=0;i<up;i++) cnt[i]+=cnt[i-1];
        for (int i=len-1;i>=0;i--) sa[--cnt[t[i]]]=id[i];
        swap(t,rk);
        p=1;
        rk[sa[0]]=0;
        for (int i=0;i<len-1;i++)
            if (sa[i]+d<len&&sa[i+1]+d<len&&t[sa[i]]==t[sa[i+1]]&&t[sa[i]+d]==t[sa[i+1]+d])
                rk[sa[i+1]]=p-1;
            else rk[sa[i+1]]=p++;
        if (p>=len) break;
        d<<=1;up=p;p=0;
    }
}
void Height(int len)
{
    int i,j,k=0;  
    for(i=1; i<=len; i++)  rank[sa[i]]=i;  
    for(i=0; i<len; i++)  
    {  
        if(k)  
            k--;  
        else  
            k=0;  
        j=sa[rank[i]-1];  
        while(w[i+k]==w[j+k])  
            k++;  
        height[rank[i]]=k;  
    } 
}
main()
{
    int len=0,up=0;
    char ch=getchar();
    while (ch>'z'||ch<'a') ch=getchar();
    while (ch>='a'&&ch<='z') w[len++]=ch-'a'+1,ch=getchar();
    while (ch>'z'||ch<'a') ch=getchar();
    int pos=len;
    w[len++]=28;
    while (ch>='a'&&ch<='z') w[len++]=ch-'a'+1,ch=getchar();
    w[len]=0;
    SA(len+1,30);
    Height(len);
    int ans=0;
    for (int i=1;i<len;i++)
        if ((sa[i]<pos)^(sa[i-1]<pos))
            ans=max(height[i],ans);
    printf("%d\n",ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值