tjut 4691

#include <iostream>  
#include <cstdio>  
#include <cstring>  
using namespace std;  
#define N 100100  
  
int sa[N],t[N],t2[N],c[N];  
char ss[N];  
int s[N];  
void build_sa(int n,int m)  
{  
    int *x=t,*y=t2;  
    for(int i=0;i<m;++i) c[i]=0;  
    for(int i=0;i<n;++i) c[x[i]=s[i]]++;  
    for(int i=1;i<m;++i) c[i]+=c[i-1];  
    for(int i=n-1;i>=0;--i) sa[--c[x[i]]]=i;  
  
    for(int k=1;k<=n;k<<=1)  
    {  
        int p=0;  
        for(int i=n-k;i<n;++i) y[p++]=i;  
        for(int i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k;  
        for(int i=0;i<m;++i) c[i]=0;  
        for(int i=0;i<n;++i) c[x[y[i]]]++;  
        for(int i=1;i<m;++i) c[i]+=c[i-1];  
        for(int i=n-1;i>=0;--i) sa[--c[x[y[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-1]]==y[sa[i]]&&y[sa[i-1]+k]==y[sa[i]+k]?p-1:p++;  
        if(p>=n) break;  
        m=p;  
    }  
}  
int rk[N],height[N];  
void cal_height(int n)  
{  
    for(int i=1;i<=n;++i) rk[sa[i]]=i;// 因为sa[0]=n  
    for(int i=0,k=0;i<n;++i)  
    {  
        if(k) k--;  
        int j=sa[rk[i]-1]; // 1<=rk[i]<=n,不会溢出  
        while(s[i+k]==s[j+k]) k++;  
        height[rk[i]]=k;// rk[i]:1-n, i:0-n-1  
    }  
}  
int d[N][30];  
void init_RMQ(int n)  
{  
    for(int i=1;i<=n;++i) d[i][0]=height[i];  
    for(int j=1;(1<<j)<=n;++j)  
        for(int i=1;i+(1<<j)-1<=n;++i)  
        d[i][j]=min(d[i][j-1],d[i+(1<<(j-1))][j-1]);  
}  
int query_RMQ(int l,int r) // 必须满足l!=r  
{  
    l=rk[l];r=rk[r];  
    if(l>r) swap(l,r); // l,r取值范围: 1-n  
    l++;  
    int k=0;  
    while((1<<(1+k))<=r-l+1) k++;  
    return min(d[l][k],d[r-(1<<k)+1][k]);  
}  
int change(int a)  
{  
    if(a<10) return 1;  
    else if(a<100) return 2;  
    else if(a<1000) return 3;  
    else if(a<10000) return 4;  
    else if(a<100000) return 5;  
}  
int n;  
int main ()  
{  
    while(scanf("%s",ss)!=EOF)  
    {  
        n=strlen(ss);  
        for(int i=0;i<n;++i)  
            s[i]=ss[i]-'a'+1;  
        s[n]=0;  
        build_sa(n+1,30);  
        cal_height(n);  
        init_RMQ(n);  
  
        int q;scanf("%d",&q);  
        long long len1=0,len2=0;  
        for(int kk=1,u,v,lcp,preu=-1,prev=-1;kk<=q;++kk)  
        {  
            scanf("%d%d",&u,&v);  
            if(preu>=0)  
            {  
                if(u==preu)  
                    lcp=n-u;  
                else lcp=query_RMQ(u,preu);  
                lcp=min(lcp,min(v-u,prev-preu));  
                len2+=change(lcp)+v-u-lcp;  
            }  
            else len2+=1+v-u;  
            len1+=v-u+1;  
            len2+=2;  
            preu=u;prev=v;  
        }  
        cout<<len1<<' '<<len2<<endl;  
    }  
    return 0;  
} 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值