HDU 4691(字尾陣列+lcp)水題
阿新 • • 發佈:2019-02-19
#include<cstdlib> #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<set> #include<map> #include<list> #include<queue> #include<vector> #define LL long long #define inf 0x7fffffff #define exp 1e-9 #define N 100009 using namespace std; int m,n,t; char s[N]; int sa[N],t1[N],t2[N],c[N]; int rank1[N],height[N]; void build_sa(int m,int n)//注意n=字串長度加1!!!! { int *x=t1,*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); x[sa[0]]=0; p=1; 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; } } void getheight(int n) { int k=0; for (int i=0; i<n; ++i ) { rank1[sa[i]]=i; } for (int i=0; i<n; ++i ) { if(k)k--; if(rank1[i]==0)// { // k=0;//k一定等於0,可省略 continue; } int j=sa[rank1[i]-1]; while(s[i+k]==s[j+k])k++; height[rank1[i]]=k; } } int f[N][30]; void init() { for(int i=0; i<=n; i++) { f[i][0]=height[i]; } for(int j=1; (1<<j)<=n; j++) for(int i=0; i+(1<<j)-1<=n; i++)//必須是<=n,WA f[i][j]=(min(f[i][j-1],f[i+(1<<(j-1))][j-1])); } int lcp(int l,int r) { int k=0; while(1<<(k+1)<=(r-l+1))k++; return min(f[l][k],f[r-(1<<k)+1][k]); } int wei(int x) { int ans=0; while(x) { ans++; x/=10; } return max(ans,1); } int main() { #ifndef ONLINE_JUDGE freopen("ex.in","r",stdin); #endif while(scanf("%s",s)==1) { n=strlen(s); build_sa(N-1,n+1); getheight(n+1); init(); LL ans1=0,ans2=0; int f=1,last=0,p=0; int q; scanf("%d",&q); while(q--) { int x,y,l; scanf("%d%d",&x,&y); l=y-x; ans1+=l+1; int tp; if(x==last)tp=l; else { if(rank1[x]<rank1[last]) tp=lcp(rank1[x]+1,rank1[last]); else tp=lcp(rank1[last]+1,rank1[x]); } tp=min(tp,p); ans2+=min(l,tp); int w=wei(min(l,tp)); ans2-=w+1; last=x; p=l; } printf("%I64d %I64d\n",ans1,ans1-ans2); } return 0; }