結果
問題 | No.2361 Many String Compare Queries |
ユーザー |
![]() |
提出日時 | 2023-01-14 18:10:36 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 1,424 ms / 2,500 ms |
コード長 | 7,057 bytes |
コンパイル時間 | 289 ms |
コンパイル使用メモリ | 82,728 KB |
実行使用メモリ | 175,364 KB |
最終ジャッジ日時 | 2024-06-30 20:40:43 |
合計ジャッジ時間 | 10,466 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 2 |
other | AC * 14 |
ソースコード
from sys import stdininput=lambda :stdin.readline()[:-1]class segtree():def __init__(self,init,func,ide):self.n=len(init)self.func=funcself.ide=ideself.size=1<<(self.n-1).bit_length()self.tree=[self.ide for i in range(2*self.size)]for i in range(self.n):self.tree[self.size+i]=init[i]for i in range(self.size-1,0,-1):self.tree[i]=self.func(self.tree[2*i], self.tree[2*i|1])def update(self,k,x):k+=self.sizeself.tree[k]=xk>>=1while k:self.tree[k]=self.func(self.tree[2*k],self.tree[k*2|1])k>>=1def get(self,i):return self.tree[i+self.size]def add(self,k,x):x+=self.get(k)self.update(k,x)def query(self,l,r):l+=self.sizer+=self.sizel_res=self.ider_res=self.idewhile l<r:if l&1:l_res=self.func(l_res,self.tree[l])l+=1if r&1:r-=1r_res=self.func(self.tree[r],r_res)l>>=1r>>=1return self.func(l_res,r_res)def debug(self,s=10):print([self.get(i) for i in range(min(self.n,s))])class string:def sa_is(s,upper):n=len(s)if n==0:return []if n==1:return [0]if n==2:if (s[0]<s[1]):return [0,1]else:return [1,0]sa=[0]*nls=[0]*nfor i in range(n-2,-1,-1):ls[i]=ls[i+1] if (s[i]==s[i+1]) else (s[i]<s[i+1])sum_l=[0]*(upper+1)sum_s=[0]*(upper+1)for i in range(n):if not(ls[i]):sum_s[s[i]]+=1else:sum_l[s[i]+1]+=1for i in range(upper+1):sum_s[i]+=sum_l[i]if i<upper:sum_l[i+1]+=sum_s[i]def induce(lms):for i in range(n):sa[i]=-1buf=sum_s[:]for d in lms:if d==n:continuesa[buf[s[d]]]=dbuf[s[d]]+=1buf=sum_l[:]sa[buf[s[n-1]]]=n-1buf[s[n-1]]+=1for i in range(n):v=sa[i]if v>=1 and not(ls[v-1]):sa[buf[s[v-1]]]=v-1buf[s[v-1]]+=1buf=sum_l[:]for i in range(n-1,-1,-1):v=sa[i]if v>=1 and ls[v-1]:buf[s[v-1]+1]-=1sa[buf[s[v-1]+1]]=v-1lms_map=[-1]*(n+1)m=0for i in range(1,n):if not(ls[i-1]) and ls[i]:lms_map[i]=mm+=1lms=[]for i in range(1,n):if not(ls[i-1]) and ls[i]:lms.append(i)induce(lms)if m:sorted_lms=[]for v in sa:if lms_map[v]!=-1:sorted_lms.append(v)rec_s=[0]*mrec_upper=0rec_s[lms_map[sorted_lms[0]]]=0for i in range(1,m):l=sorted_lms[i-1]r=sorted_lms[i]end_l=lms[lms_map[l]+1] if (lms_map[l]+1<m) else nend_r=lms[lms_map[r]+1] if (lms_map[r]+1<m) else nsame=Trueif end_l-l!=end_r-r:same=Falseelse:while(l<end_l):if s[l]!=s[r]:breakl+=1r+=1if (l==n) or (s[l]!=s[r]):same=Falseif not(same):rec_upper+=1rec_s[lms_map[sorted_lms[i]]]=rec_upperrec_sa=string.sa_is(rec_s,rec_upper)for i in range(m):sorted_lms[i]=lms[rec_sa[i]]induce(sorted_lms)return sadef suffix_array_upper(s,upper):assert 0<=upperfor d in s:assert 0<=d and d<=upperreturn string.sa_is(s,upper)def suffix_array(s):n=len(s)if type(s)==str:s2=[ord(i) for i in s]return string.sa_is(s2,255)else:idx=list(range(n))idx.sort(key=lambda x:s[x])s2=[0]*nnow=0for i in range(n):if (i& s[idx[i-1]]!=s[idx[i]]):now+=1s2[idx[i]]=nowreturn string.sa_is(s2,now)def lcp_array(s,sa):n=len(s)assert n>=1rnk=[0]*nfor i in range(n):rnk[sa[i]]=ilcp=[0]*(n-1)h=0for i in range(n):if h>0:h-=1if rnk[i]==0:continuej=sa[rnk[i]-1]while(j+h<n and i+h<n):if s[j+h]!=s[i+h]:breakh+=1lcp[rnk[i]-1]=hreturn lcpdef z_algorithm(s):n=len(s)if n==0:return []z=[0]*ni=1;j=0while(i<n):z[i]=0 if (j+z[j]<=i) else min(j+z[j]-i,z[i-j])while((i+z[i]<n) and (s[z[i]]==s[i+z[i]])):z[i]+=1if (j+z[j]<i+z[i]):j=ii+=1z[0]=nreturn zclass SparseTable:def __init__(self,init,func,e):n=len(init)self.e=eself.func=funcsize=0while (1<<size)<=n:size+=1self.size=sizeself.table=[e]*(size*(1<<size))for i in range(n):self.table[i]=init[i]for i in range(1,size):for j in range((1<<size)-(1<<i)+1):self.table[(i<<size)+j]=func(self.table[((i-1)<<size)+j],self.table[((i-1)<<size)+j+(1<<(i-1))])def query(self,l,r):if l==r:return self.es=(r-l).bit_length()-1return self.func(self.table[(s<<self.size)+l],self.table[(s<<self.size)+r-(1<<s)])n,q=map(int,input().split())S=input()SA=string.suffix_array(S)LCP=string.lcp_array(S,SA)p=[0]*nfor i in range(n):p[SA[i]]=iST=SparseTable(LCP,min,10**9)query=[[] for i in range(n)]for i in range(q):L,R=map(lambda x:int(x)-1,input().split())d=R-L+1ng,ok=-1,p[L]while ok-ng>1:mid=(ng+ok)//2if ST.query(mid,p[L])>=d:ok=midelse:ng=midquery[ok].append((d,i))cum=[0]*nfor i in range(1,n):cum[i]=cum[i-1]+(n-SA[i-1])ans=[0]*qseg1=segtree([0]*(n+1),lambda x,y:x+y,0)seg2=segtree([0]*(n+1),lambda x,y:x+y,0)stc=[]for i in range(n-1,-1,-1):if i!=n-1:res=0while stc and stc[-1][0]>=LCP[i]:res+=stc[-1][1]x=stc.pop()[0]seg1.update(x,0)seg2.update(x,0)if res!=0 and LCP[i]!=0:seg1.update(LCP[i],LCP[i]*res)seg2.update(LCP[i],res)stc.append((LCP[i],res))seg1.add(n-SA[i],n-SA[i])seg2.add(n-SA[i],1)stc.append((n-SA[i],1))for d,idx in query[i]:ans[idx]+=cum[i]+seg1.query(0,d)+seg2.query(d,n+1)*(d-1)print(*ans,sep='\n')