結果
問題 | No.2626 Similar But Different Name |
ユーザー |
![]() |
提出日時 | 2024-02-13 14:12:42 |
言語 | PyPy3 (7.3.15) |
結果 |
AC
|
実行時間 | 1,335 ms / 3,000 ms |
コード長 | 9,892 bytes |
コンパイル時間 | 147 ms |
コンパイル使用メモリ | 82,548 KB |
実行使用メモリ | 256,832 KB |
最終ジャッジ日時 | 2024-09-28 18:23:19 |
合計ジャッジ時間 | 22,759 ms |
ジャッジサーバーID (参考情報) |
judge5 / judge2 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 3 |
other | AC * 35 |
ソースコード
from collections import Counter# SA-IS (O(nlogn))# s: 文字列def sais(s):uniq = list(set(s))uniq.sort()return sais_rec(list(map({e: i+1 for i, e in enumerate(uniq)}.__getitem__, s)), len(uniq))def sais_rec(lst, num):L = len(lst)if L < 2:return lst + [0]lst = lst + [0]L += 1res = [-1] * Lt = [1] * Lfor i in range(L-2, -1, -1):t[i] = 1 if (lst[i] < lst[i+1] or (lst[i] == lst[i+1] and t[i+1])) else 0isLMS = [t[i-1] < t[i] for i in range(L)]LMS = [i for i in range(1, L) if t[i-1] < t[i]]LMSn = len(LMS)count = Counter(lst)tmp = 0cstart = [0]*(num+1)cend = [0]*(num+1)for key in range(num+1):cstart[key] = tmpcend[key] = tmp = tmp + count[key]cc_it = [iter(range(e-1, s-1, -1)) for s, e in zip(cstart, cend)]for e in reversed(LMS):res[next(cc_it[lst[e]])] = ecs_it = [iter(range(s, e)) for s, e in zip(cstart, cend)]ce_it = [iter(range(e-1, s-1, -1)) for s, e in zip(cstart, cend)]for e in res:if e > 0 and not t[e-1]:res[next(cs_it[lst[e-1]])] = e-1for e in reversed(res):if e > 0 and t[e-1]:res[next(ce_it[lst[e-1]])] = e-1name = 0; prev = -1pLMS = {}for e in res:if isLMS[e]:if prev == -1 or lst[e] != lst[prev]:name += 1; prev = eelse:for i in range(1, L):if lst[e+i] != lst[prev+i]:name += 1; prev = ebreakif isLMS[e+i] or isLMS[prev+i]:breakpLMS[e] = name-1if name < LMSn:sublst = [pLMS[e] for e in LMS if e < L-1]ret = sais_rec(sublst, name-1)LMS = list(map(LMS.__getitem__, reversed(ret)))else:LMS = [e for e in reversed(res) if isLMS[e]]res = [-1] * Lcc_it = [iter(range(e-1, s-1, -1)) for s, e in zip(cstart, cend)]for e in LMS:res[next(cc_it[lst[e]])] = ecs_it = [iter(range(s, e)) for s, e in zip(cstart, cend)]ce_it = [iter(range(e-1, s-1, -1)) for s, e in zip(cstart, cend)]for e in res:if e > 0 and not t[e-1]:res[next(cs_it[lst[e-1]])] = e-1for e in reversed(res):if e > 0 and t[e-1]:res[next(ce_it[lst[e-1]])] = e-1return res# Longest Common Prefix# (文字列s, 文字列長n, Suffix Array)を引数として与えるdef LCP(s, n, sa):lcp = [-1]*(n+1)rank = [0]*(n+1)for i in range(n+1): rank[sa[i]] = ih = 0lcp[0] = 0for i in range(n):j = sa[rank[i] - 1]if h > 0: h -= 1while j+h < n and i+h < n and s[j+h]==s[i+h]:h += 1lcp[rank[i] - 1] = hreturn lcp#https://github.com/shakayami/ACL-for-python/blob/master/convolution.pyclass FFT():def primitive_root_constexpr(self,m):if m==2:return 1if m==167772161:return 3if m==469762049:return 3if m==754974721:return 11if m==998244353:return 3divs=[0]*20divs[0]=2cnt=1x=(m-1)//2while(x%2==0):x//=2i=3while(i*i<=x):if (x%i==0):divs[cnt]=icnt+=1while(x%i==0):x//=ii+=2if x>1:divs[cnt]=xcnt+=1g=2while(1):ok=Truefor i in range(cnt):if pow(g,(m-1)//divs[i],m)==1:ok=Falsebreakif ok:return gg+=1def bsf(self,x):res=0while(x%2==0):res+=1x//=2return resrank2=0root=[]iroot=[]rate2=[]irate2=[]rate3=[]irate3=[]def __init__(self,MOD):self.mod=MODself.g=self.primitive_root_constexpr(self.mod)self.rank2=self.bsf(self.mod-1)self.root=[0 for i in range(self.rank2+1)]self.iroot=[0 for i in range(self.rank2+1)]self.rate2=[0 for i in range(self.rank2)]self.irate2=[0 for i in range(self.rank2)]self.rate3=[0 for i in range(self.rank2-1)]self.irate3=[0 for i in range(self.rank2-1)]self.root[self.rank2]=pow(self.g,(self.mod-1)>>self.rank2,self.mod)self.iroot[self.rank2]=pow(self.root[self.rank2],self.mod-2,self.mod)for i in range(self.rank2-1,-1,-1):self.root[i]=(self.root[i+1]**2)%self.modself.iroot[i]=(self.iroot[i+1]**2)%self.modprod=1;iprod=1for i in range(self.rank2-1):self.rate2[i]=(self.root[i+2]*prod)%self.modself.irate2[i]=(self.iroot[i+2]*iprod)%self.modprod=(prod*self.iroot[i+2])%self.modiprod=(iprod*self.root[i+2])%self.modprod=1;iprod=1for i in range(self.rank2-2):self.rate3[i]=(self.root[i+3]*prod)%self.modself.irate3[i]=(self.iroot[i+3]*iprod)%self.modprod=(prod*self.iroot[i+3])%self.modiprod=(iprod*self.root[i+3])%self.moddef butterfly(self,a):n=len(a)h=(n-1).bit_length()LEN=0while(LEN<h):if (h-LEN==1):p=1<<(h-LEN-1)rot=1for s in range(1<<LEN):offset=s<<(h-LEN)for i in range(p):l=a[i+offset]r=a[i+offset+p]*rota[i+offset]=(l+r)%self.moda[i+offset+p]=(l-r)%self.modrot*=self.rate2[(~s & -~s).bit_length()-1]rot%=self.modLEN+=1else:p=1<<(h-LEN-2)rot=1imag=self.root[2]for s in range(1<<LEN):rot2=(rot*rot)%self.modrot3=(rot2*rot)%self.modoffset=s<<(h-LEN)for i in range(p):a0=a[i+offset]a1=a[i+offset+p]*rota2=a[i+offset+2*p]*rot2a3=a[i+offset+3*p]*rot3a1na3imag=(a1-a3)%self.mod*imaga[i+offset]=(a0+a2+a1+a3)%self.moda[i+offset+p]=(a0+a2-a1-a3)%self.moda[i+offset+2*p]=(a0-a2+a1na3imag)%self.moda[i+offset+3*p]=(a0-a2-a1na3imag)%self.modrot*=self.rate3[(~s & -~s).bit_length()-1]rot%=self.modLEN+=2def butterfly_inv(self,a):n=len(a)h=(n-1).bit_length()LEN=hwhile(LEN):if (LEN==1):p=1<<(h-LEN)irot=1for s in range(1<<(LEN-1)):offset=s<<(h-LEN+1)for i in range(p):l=a[i+offset]r=a[i+offset+p]a[i+offset]=(l+r)%self.moda[i+offset+p]=(l-r)*irot%self.modirot*=self.irate2[(~s & -~s).bit_length()-1]irot%=self.modLEN-=1else:p=1<<(h-LEN)irot=1iimag=self.iroot[2]for s in range(1<<(LEN-2)):irot2=(irot*irot)%self.modirot3=(irot*irot2)%self.modoffset=s<<(h-LEN+2)for i in range(p):a0=a[i+offset]a1=a[i+offset+p]a2=a[i+offset+2*p]a3=a[i+offset+3*p]a2na3iimag=(a2-a3)*iimag%self.moda[i+offset]=(a0+a1+a2+a3)%self.moda[i+offset+p]=(a0-a1+a2na3iimag)*irot%self.moda[i+offset+2*p]=(a0+a1-a2-a3)*irot2%self.moda[i+offset+3*p]=(a0-a1-a2na3iimag)*irot3%self.modirot*=self.irate3[(~s & -~s).bit_length()-1]irot%=self.modLEN-=2def convolution(self,a,b):n=len(a);m=len(b)if not(a) or not(b):return []if min(n,m)<=40:res=[0]*(n+m-1)for i in range(n):for j in range(m):res[i+j]+=a[i]*b[j]res[i+j]%=self.modreturn resz=1<<((n+m-2).bit_length())a=a+[0]*(z-n)b=b+[0]*(z-m)self.butterfly(a)self.butterfly(b)c=[(a[i]*b[i])%self.mod for i in range(z)]self.butterfly_inv(c)iz=pow(z,self.mod-2,self.mod)for i in range(n+m-1):c[i]=(c[i]*iz)%self.modreturn c[:n+m-1]def nibun(f):left,right=-1,N+1while right-left>1:mid=(right+left)//2if f(mid):left=midelse:right=midreturn rightdef isok(n):pos=sa[n]if S[pos:].upper()<T.upper():return Truereturn Falsedef isok2(n):pos=sa[n]if S[pos:].upper()<T.upper()+'z':return Truereturn FalseN,M,K=map(int,input().split())S=input()T=input()sa=sais(S.upper())one=nibun(isok)two=nibun(isok2)s=[]t=[]for si in S:if si.isupper():s.append(1)else:s.append(-1)for si in T:if si.isupper():t.append(1)else:t.append(-1)fft=FFT(998244353)fa=fft.convolution(s,t[::-1])ans=0for i in range(one,two):tmp=fa[sa[i]+M-1]if tmp>=10**8:tmp-=998244353if M>tmp>=M-K*2:ans+=1print(ans)