算模版?,不过这东西,顺着思路很好写啊
题目读不懂。。。所以只有rmq和后缀数组是我写的,但是我也是想联系一下后缀数组求lcp,其实没法说吧,顺着st算法的理论写就行
不过为什么log求rmq_st的k,会wa,但是循环判断就不会?????
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<iostream>
#define M(x) memset(x,0,sizeof(x))
using namespace std;
const int N=100005;
int sa[N],c[N],t1[N],t2[N],s[N],height[N],rk[N],f[N][22],n;
char ch[N];
void clear()
{
M(sa);M(c);M(t1);M(t2);M(height);M(rk);M(f);M(s);
}
void build_sa()
{
int m=29,*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]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;
if (p>=n) break;
m=p;
}
}
void build_height()
{
int k=0;
for (int i=0;i<n;i++) rk[sa[i]]=i;
for (int i=0;i<n-1;i++)
{
if (k) k--;
int j=sa[rk[i]-1];
while (s[j+k]==s[i+k]) k++;
height[rk[i]]=k;
}
}
void build_st()
{
for (int i=0;i<n;i++) f[i][0]=height[i];
for (int k=1;(1<<k)<=n;k++)
for (int i=0;i<n;i++)
if (i+(1<<k)-1<n) f[i][k]=min(f[i][k-1],f[i+(1<<(k-1))][k-1]);
}//预处理,第0名其实是不用算的,因为第0名是哨兵元素啊,我们需用的都是排在1~n-1之间的元素
int query_RMQ(int u,int v)
{
int l=rk[u],r=rk[v];
if (l>r) swap(l,r);
l++;
int k=0;
while((1<<(1+k))<=r-l+1) k++;///为什么我用log过不了???,这里就是只要2^k乘2<=长度,那么就再把k++
return min(f[l][k],f[r-(1<<k)+1][k]);
}//rmq
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 main ()
{
while(scanf("%s",ch)!=EOF)
{
n=strlen(ch);
for(int i=0;i<n;++i)
s[i]=ch[i]-'a'+1;
s[n++]=0;
build_sa();
build_height();
build_st();
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;
}