QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#874826#897. 基本子串字典2020HZ06WA 162ms380640kbC++144.2kb2025-01-28 17:46:442025-01-28 17:46:45

Judging History

This is the latest submission verdict.

  • [2025-01-28 17:46:45]
  • Judged
  • Verdict: WA
  • Time: 162ms
  • Memory: 380640kb
  • [2025-01-28 17:46:44]
  • Submitted

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,pos),mn=min(mn,pos),cnt+=R.len();
	}
	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: 110ms
memory: 311732kb

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
Wrong Answer
time: 162ms
memory: 380640kb

input:

mmrqqmrrqmkhmkmkmkbhmhmgncyrhnbrrimkmkmktmkhmkhmkhqbsqbmmmmmmkhmkhqkhmkhqmkmkmkmkappsohmkhqkhmhmkhqkhmmbqbmmmmmmqbmmmmmmuwyvkbhkbhkbhkbhkbhbqbmmmmmmqbqbmmmmmmqbqbmmmmmmqihqkhmkhqmkmhqkhmkhqmkmymkhqmkmyvdnjurrimkmkmktrrimkmkmktrrimkmkmktynjurrimkmkmktnjurrimkmkmktnjurrimkmkmktrhnbrrimkmkmktrhnbrrimkm...

output:

556 1853 2
13 1254 7
12 1493 9
405 1071 2
1119 1119 1
6 394 5
1137 1137 1
4 795 3
6 1326 4
4 1084 4
359 1613 3
5 288 4
16 1738 7
79 710 2
7 1500 8
589 589 1
138 1510 3
136 1774 8
4 1886 10
2 1978 4
4 1886 10
589 1944 2
948 948 1
201 1498 2
345 345 1
11 1366 2
136 838 4
310 1665 2
39 1761 3
1093 2448...

result:

wrong answer 237th lines differ - expected: '26 1196 6', found: '26 1196 7'