hdu 4691 lcp最长公共前缀 后缀数组经典模板

来源:互联网 发布:蚁群算法基本流程图 编辑:程序博客网 时间:2024/04/19 12:15

每行无论公共前缀是多少,都要一个空格和换行,+2

注意公共前缀的长度

#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define N 100100int 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;}


原创粉丝点击