hdu 4691 后缀数组+rmq 求子串lcp
利用RMQ求子串lcp的基础题,这个板子是我之前的,比较蠢的一种实现
后面试试用最新的板子AC一下
#include<bits/stdc++.h>
#define ll long long
#define rep(ii,a,b) for(int ii=a;ii<=b;++ii)
#define per(ii,a,b) for(int ii=b;ii>=a;--ii)
using namespace std;
const int maxn=2e5+10,maxm=2e6+10;
const ll INF=0x3f3f3f3f,mod=1e9+7;
int casn,n,m,k;
const int csize=131;
char s[maxn];
class suffix{public:
int sa[maxn],rank[maxn],h[maxn];
int wa[maxn],wb[maxn],wc[maxn],wd[maxn];
char *str;
void geth(int n){
int i,j,k=0;
for(i=1;i<=n;++i) rank[sa[i]]=i;
for(i=0;i<n;h[rank[i++]]=k)
for(k?k--:0,j=sa[rank[i]-1];str[i+k]==str[j+k];++k);
}
void getsa(char *_s,int n,int m){
str=_s;
int i,j,p,*x=wa,*y=wb,*t;
for(int i=0;i<m;++i) wd[i]=0;
for(int i=0;i<n;++i) wd[x[i]=str[i]]++;
for(int i=1;i<m;++i) wd[i]+=wd[i-1];
for(int i=n-1;i>=0;--i) sa[--wd[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) wc[i]=x[y[i]];
for(i=0;i<m;++i) wd[i]=0;
for(i=0;i<n;++i) wd[wc[i]]++;
for(i=1;i<m;++i) wd[i]+=wd[i-1];
for(i=n-1;i>=0;--i) sa[--wd[wc[i]]]=y[i];
for(swap(x,y),p=1,x[sa[0]]=0,i=1;i<n;++i)
x[sa[i]]=y[sa[i-1]]==y[sa[i]]&&y[sa[i-1]+j]==y[sa[i]+j]?p-1:p++;
}
geth(n-1);
}
}suf;
class stable{public:
int dp[21][maxn];
void cal(int *a,int n){
rep(i,1,n) dp[0][i]=a[i];
for(int j=1;(1<<j)<=n;j++) for(int i=1;i+(1<<j)-1<=n;++i)
dp[j][i]=min(dp[j-1][i],dp[j-1][i+(1<<(j-1))]);
}
int query(int l,int r){
int lg=0;
while((1<<(lg+1))<=r-l+1) ++lg;
return min(dp[lg][l],dp[lg][r-(1<<lg)+1]);
}
}st;
int main() {
while(cin>>(s)){
n=strlen(s);s[n]='0';
suf.getsa(s,n+1,233);
st.cal(suf.h,n);
cin>>m;
ll ans1=m,ans2=2*m+1;
ll a,b;cin>>a>>b;
ans1+=b-a;ans2+=b-a;
m--;
while(m--){
ll c,d,len;cin>>c>>d;
if(c==a) len=min(d-c,b-a);
else {
int s=suf.rank[a],t=suf.rank[c];
if(s>t) swap(s,t);
len=st.query(s+1,t);
}
len=min(len,min(d-c,b-a));
ans2+=d-c-len;
if(!len) ans2++;
else ans2+=int(log10(len)+1);
ans1+=d-c;
a=c,b=d;
}
cout<<ans1<<' '<<ans2<<endl;
}
return 0;
}

浙公网安备 33010602011771号