准备学习后缀数组 先存一个论文里的模板

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>

using namespace std;

#define F(x) ((x) / 3 + ((x) % 3 == 1 ? 0 : tb))
#define G(x) ((x) < tb ? (x) * 3 + 1 :((x) - tb) * 3 + 2)
const int MAXN = 300010;
const int MAXM = 100010;
char input[MAXM];
int wa[MAXN],wb[MAXN],ws[MAXN],wv[MAXN],wsd[MAXN],r[MAXN],sa[MAXN];
int num[MAXN];
char str[MAXN];
int dp[MAXM][25];
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 mysort(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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) b[--wsd[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;
    mysort(r + 2,wa,wb,tbc,m);
    mysort(r + 1,wb,wa,tbc,m);
    mysort(r,wa,wb,tbc,m);
    for(p = 1,rn[F(wb[0])] = 0,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;
    mysort(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++];
    for(; i < ta ; p++) sa[p] = wa[i++];
    for(; j < tbc ; p++) sa[p] = wb[j++];
}


int cmp(int *r,int a,int b,int l)
{
    return r[a ]== r[b] && r[a + l] == r[b + l];
}
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++) wsd[i] = 0;
    for(i = 0 ; i < n ; i++) wsd[x[i] = r[i]]++;
    for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
    for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[x[i]]] = i;
    for(j = 1 , p = 1 ; p < n ; j *= 2,m = p)
    {
        for(p = 0 ,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 < n ; i++) wv[i] = x[y[i]];
        for(i = 0 ; i < m ; i++) wsd[i] = 0;
        for(i = 0 ; i < n ; i++) wsd[wv[i]]++;
        for(i = 1 ; i < m ; i++) wsd[i] += wsd[i - 1];
        for(i = n - 1 ; i >= 0 ; i--) sa[--wsd[wv[i]]] = y[i];
        for(t = x,x = y,y = t,p = 1,x[sa[0]] = 0,i = 1; i < n ; i++)
            x[sa[i]] = cmp(y,sa[i - 1],sa[i],j) ? p - 1 : p++;
    }
}

int Rank[MAXN],height[MAXN];
void calheight(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 ; height[Rank[i++]] = k)
        for(k ? k--:0,j = sa[Rank[i] - 1] ; r[i + k]==r[j + k]; k++);
}

void RMQ_init(int n,int b[])
{
    int i,j;
    for(i = 1 ; i <= n ; i++)
        dp[i][0] = b[i];
    for(j = 1 ; (1 << j) <= n ; j++)
        for(i = 1 ; i + (1 << j) - 1 <= n ; i++)
            dp[i][j] = min(dp[i][j - 1],dp[i + (1<<(j - 1))][j - 1]);
}

int rmq(int s,int v)
{
    s = Rank[s],v = Rank[v];
    if(s > v)swap(s,v);
    s++;
    int k=(int)(log((v - s + 1)*1.0)/log(2.0));
    return min(dp[s][k],dp[v - (1 << k) + 1][k]);
}
int main()
{
    while (scanf ("%s",input)!=EOF)
    {
        int len=strlen(input);
        for (int i=0;i<len;i++)
        {
            num[i]=input[i]-'0'+1;
        }
        num[len]=0;
        dc3(num,sa,len + 1,11);//带上自定义最小的那个的种类数
        calheight(num,sa,len+1);
        for (int i=0;i<len;i++)
            printf ("%d ",Rank[i]);printf ("\n");
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/nj-czy/p/5732890.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值