QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#874833 | #897. 基本子串字典 | 2020HZ06 | RE | 100ms | 311100kb | C++14 | 4.2kb | 2025-01-28 17:53:47 | 2025-01-28 17:53:47 |
Judging History
answer
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define pb push_back
const int N=200005,m=127,P=1000007,p=131;
const ull mod=212370440130137957ll;
int n,q;
char s[N];
ull W[2],pw[N];
mt19937_64 rd(time(0));
inline int get(int x,int l){return (x-1)/l+1;}
inline int L(int x,int l){return (x-1)*l+1;}
inline int R(int x,int l){return min(n,x*l);}
struct seq{//等差数列
int st=0,ed=0,d=0;//首项、末项、公差
seq seg(int l,int r){//提取
l=max(l,st),r=min(r,ed);
if(!st) return {0,0,0};
if(!d){
if(l==st&&r==st) return {st,ed,0};
return {0,0,0};
}
l=(l-st+d-1)/d*d+st,r=(r-st)/d*d+st;
if(l>r) return {0,0,0};
return {l,r,l==r?0:d};
}
int len(){return d?(ed-st)/d+1:st>0;}//项数
bool in(int p){return p>=st&&p<=ed&&(d?(p-st)%d==0:(st&&p==st));}//是否出现
};
void upd(seq &a,int p){//更新
if(!a.st) a.st=p;
else if(!a.d) a.d=p-a.st;
a.ed=p;
}
seq merge(seq a,seq b){//合并
seq res;
if(a.len()==1&&b.len()==1&&a.st<b.ed) res.d=b.ed-a.st;
else res.d=max(a.d,b.d);
res.st=a.st?a.st:b.st,res.ed=b.ed?b.ed:a.ed;
if(res.st==res.ed) res.d=0;
return res;
}
seq cap(seq a,seq b){//求交
if(a.len()<b.len()) swap(a,b);
if(b.len()==0) return b;
seq res;
if(b.len()<=2){
if(a.in(b.st)) upd(res,b.st);
if(b.len()==2&&a.in(b.ed)) upd(res,b.ed);
}
else{
res.d=a.d,res.st=max(a.st,b.st),res.ed=min(a.ed,b.ed);
if(res.st>res.ed) res={0,0,0};
else if(res.st==res.ed) res.d=0;
}
return res;
}
struct Hash{//二元组(块编号、子串)哈希
int h[P],nxt[N],bl[N],ct;
ull s[N];
seq g[N];
void ins(int B,ull has,int p){
int key=(B*W[0]+has*W[1])%P;
for(int i=h[key];i;i=nxt[i]) if(bl[i]==B&&s[i]==has) {upd(g[i],p);return;}
++ct,bl[ct]=B,s[ct]=has,nxt[ct]=h[key],h[key]=ct,upd(g[ct],p);
}
seq fd(int B,ull has){
int key=(B*W[0]+has*W[1])%P;
for(int i=h[key];i;i=nxt[i]) if(bl[i]==B&&s[i]==has) return g[i];
return {0,0,0};
}
};
struct dic{//基本子串字典
int sa[N],rk[N],old[N],tmp[N],buc[N],pr[20][N]={0};
ull h[20][N]={0};//hash 值
Hash s[20];// hash 表
void solve(int d,int c){
int w=1<<d,ct=0;
for(int i=1;i<n;i++) if(sa[i]+w-1<=n&&rk[sa[i]]==rk[sa[i+1]]) pr[d][sa[i+1]]=sa[i];
for(int i=1;i+w*2-1<=n;i++){//计算哈希值
h[d+1][i]=(h[d][i]+pw[1<<d]*h[d][i+w])%mod;
s[d+1].ins(get(i,w*2),h[d+1][i],i);//更新块内信息
}
for(int i=n-w+1;i<=n;i++) tmp[++ct]=i;
for(int i=1;i<=n;i++)
if(sa[i]>w) tmp[++ct]=sa[i]-w;
memset(buc,0,sizeof(buc));
for(int i=1;i<=n;i++) buc[rk[i]]++;
for(int i=1;i<=c;i++) buc[i]+=buc[i-1];
for(int i=n;i>=1;i--) sa[buc[rk[tmp[i]]]--]=tmp[i];
memcpy(old,rk,sizeof(rk));
c=0;
for(int i=1;i<=n;i++){
if(old[sa[i]]==old[sa[i-1]]&&old[sa[i]+w]==old[sa[i-1]+w]) rk[sa[i]]=c;
else rk[sa[i]]=++c;
}
if(c==n) return;
solve(d+1,c);
}
void build(char *S){
memset(buc,0,sizeof(buc));
for(int i=1;i<=n;i++) buc[rk[i]=S[i]]++,h[0][i]=S[i],s[0].ins(i,S[i],i);
for(int i=1;i<=m;i++) buc[i]+=buc[i-1];
for(int i=n;i>=1;i--) sa[buc[rk[i]]--]=i;
solve(0,m);
}
seq mat(int l,int r,int x,int y,int k){//匹配
int b1=get(x,(1<<k)),b2=get(y,(1<<k));ull H=h[k][l];
seq r1=s[k].fd(b1,H).seg(x,y),r2=s[k].fd(b2,H).seg(x,y);
return merge(s[k].fd(b1,H).seg(x,y),s[k].fd(b2,H).seg(x,y));
}
}D[2];
void query(int l,int r){//求最长 border、最短 border、border 个数
int mx=0,mn=0x3f3f3f3f,cnt=0;
for(int i=0;(1<<i)<r-l+1;i++){
int v=1<<i,v1=min(v*2,r-l+1)-1;
seq r1=D[0].mat(l,l+v-1,r-v1+1,r-v+1,i),r2=D[1].mat(n-r+1,n-(r-v+1)+1,n-(l+v1-1)+1,n-(l+v-1)+1,i);
if(r1.st) r1.st=r-r1.st+1,r1.ed=r-r1.ed+1,swap(r1.st,r1.ed);
if(r2.st) r2.st=n-l+1-r2.st+1,r2.ed=n-l+1-r2.ed+1,swap(r2.st,r2.ed);
seq R=cap(r1,r2);
int pos=R.ed;
if(pos) mx=max(mx,R.ed),mn=min(mn,R.st),cnt+=R.len(),assert(R.st>=v&&R.ed<=v1);
}
if(cnt) printf("%d %d %d\n",mn,mx,cnt);
else printf("-1\n");
}
int main(){
int l,r;
scanf("%s%d",s+1,&q);
n=strlen(s+1);
pw[0]=1,W[0]=rd(),W[1]=rd();
for(int i=1;i<=n;i++) pw[i]=pw[i-1]*p%mod;
D[0].build(s),reverse(s+1,s+n+1),D[1].build(s);//正反串都建一遍
while(q--){
scanf("%d%d",&l,&r),l++,r++;
query(l,r);
}
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 100ms
memory: 311100kb
input:
ejdzjvhfouduzopksvrmktcerxlnwcaspfztkzjcguzbkloievrzdxutubkvhpwzedsebpjscfhswjzqanpdwjlljxubvoyuaauwxyyjzoryfthvjkbwqbippholdbmrpszwzuhkxxktzclviearfkwdegsrwjttxymiepczmgilmplnvulwbmlngpkxgcvyizlpzwuqfqxcneyjtkozanlkwkdqzsjjberqnyvlqoxrrkpbhyrlugfkwiepnjewhqjqhsursplcpznzfljvdzcrigjjxsmegrrhzetnvzql...
output:
-1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 1 1 1 -1 -1 -1 -1 -1 -1 -1 ...
result:
ok 50000 lines
Test #2:
score: -100
Runtime Error
input:
mmrqqmrrqmkhmkmkmkbhmhmgncyrhnbrrimkmkmktmkhmkhmkhqbsqbmmmmmmkhmkhqkhmkhqmkmkmkmkappsohmkhqkhmhmkhqkhmmbqbmmmmmmqbmmmmmmuwyvkbhkbhkbhkbhkbhbqbmmmmmmqbqbmmmmmmqbqbmmmmmmqihqkhmkhqmkmhqkhmkhqmkmymkhqmkmyvdnjurrimkmkmktrrimkmkmktrrimkmkmktynjurrimkmkmktnjurrimkmkmktnjurrimkmkmktrhnbrrimkmkmktrhnbrrimkm...