题目链接:hdu 6068 Classic Quotation
题意:
给你两个字符串S和T,现在有q个询问,每个询问给出一个l,r,问S[1..i] 和 S[j..n](1≤i≤L,R≤j≤n)中有多少个T,求出全部的总和。
题解:
Claris的官方题解:
这里我用hash代替了kmp的作用。
1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=(a);i<=(b);++i) 3 using namespace std; 4 typedef long long ll; 5 using ull = unsigned long long ; 6 7 const int N=5e4+7; 8 int t,n,m,q,pre[N][101],suf[N][101],L[N],R[N],l,r; 9 char S[N],T[N]; 10 ull b[N]; 11 struct string_hash 12 { 13 static const int seed=131; 14 ull h[N]; 15 inline int idx(char x){return x-‘a‘+1;} 16 static void init(){b[0]=1;F(i,1,N-1)b[i]=b[i-1]*seed;} 17 void ins(char *s,int len) 18 { 19 h[0]=1; 20 F(i,1,len)h[i]=h[i-1]*seed+idx(s[i]); 21 } 22 inline ull ask(int l,int r){return h[r]-b[r-l+1]*h[l-1];} 23 }A,B; 24 25 int main(){ 26 scanf("%d",&t); 27 string_hash::init(); 28 while(t--) 29 { 30 scanf("%d%d%d",&n,&m,&q); 31 scanf("%s%s",S+1,T+1); 32 A.ins(S,n),B.ins(T,m); 33 F(i,1,n)for(int l=1,en=min(m,i);l<=en;++l) 34 pre[i][l]=(A.ask(i-l+1,i)==B.ask(1,l)); 35 reverse(S+1,S+n+1),reverse(T+1,T+m+1); 36 A.ins(S,n),B.ins(T,m); 37 F(i,1,n)for(int l=1,en=min(m,i);l<=en;++l) 38 suf[i][l]=(A.ask(i-l+1,i)==B.ask(1,l)); 39 for(int i=1,cnt=0;i<=n;++i) 40 cnt+=pre[i][m],L[i]=L[i-1]+cnt; 41 for(int i=1,cnt=0;i<=n;++i) 42 cnt+=suf[i][m],R[i]=R[i-1]+cnt; 43 F(i,1,n)F(j,1,m) 44 pre[i][j]+=pre[i-1][j],suf[i][j]+=suf[i-1][j]; 45 while(q--) 46 { 47 scanf("%d%d",&l,&r);r=n-r+1; 48 ll ans=1ll*L[l]*r+1ll*R[r]*l; 49 F(i,1,m-1)ans+=1ll*pre[l][i]*suf[r][m-i]; 50 printf("%lld\n",ans); 51 } 52 } 53 return 0; 54 }
时间: 2024-11-02 23:39:44