hdu 6068 Classic Quotation(字符串hash)

题目链接:hdu 6068 Classic Quotation

题意:

给你两个字符串S和T,现在有q个询问,每个询问给出一个l,r,问S[1..i] 和 S[j..n](1iL,Rjn)中有多少个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 }
View Code

 

转载于:https://www.cnblogs.com/bin-gege/p/7290516.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值