hdu 6068 Classic Quotation(字符串hash)

题目链接: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-08-27 12:34:38

hdu 6068 Classic Quotation(字符串hash)的相关文章

HDU 6068 Classic Quotation KMP+DP

Classic Quotation Problem Description When online chatting, we can save what somebody said to form his ''Classic Quotation''. Little Q does this, too. What's more? He even changes the original words. Formally, we can assume what somebody said as a st

hdu 1880 魔咒词典(字符串hash)

题目链接:hdu 1880 魔咒词典 题意: 给你一个10w的词典,让你输出对应的字段. 题解: map暴力存字符串肯定会卡内存,这里用BKDR字符串hash一下,用map映射一下. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 typedef unsigned long long ull; 5 6 const int N=1e5+7,seed=133

hdu 3973 字符串hash+线段树

http://acm.hdu.edu.cn/showproblem.php?pid=3973 Problem Description You are given some words {Wi}. Then our stupid AC will give you a very long string S. AC is stupid and always wants to know whether one substring from S exists in the given words {Wi}

hdu 4821 字符串hash+map判重 String (长春市赛区I题)

http://acm.hdu.edu.cn/showproblem.php?pid=4821 昨晚卡了非常久,開始TLE,然后优化了之后,由于几个地方变量写混.一直狂WA.搞得我昨晚都失眠了,,. 这几次hash军写错的变量--tmp=(j==m-1)?ah[j]:(ah[j]-ah[j-m]*base[m]);  外层循环变量是i,我写的字符串hash的几题都写成tmp=(i==0)? ah[j]:(ah[j]-ah[j-m]*base[m]); 二逼啊 题目大意: 给定一个字符串(最长10^

HDU 4821 字符串hash

题目大意: 希望找到连续的长为m*l的子串,使得m个l长的子串每一个都不一样,问能找到多少个这样的子串 简单的字符串hash,提前预处理出每一个长度为l的字符串的hash值 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <map> 6 #include <set> 7 8 using na

HDU 5763 Another Meaning dp+字符串hash

题意:给定一个句子str,和一个单词sub,这个单词sub可以翻译成两种不同的意思,问这个句子一共能翻译成多少种不能的意思 例如:str:hehehe   sub:hehe 那么,有**he.he**.和hehehe三种不同的意思, 考虑一下aaadaaa这种情况?sub:aa  前面的aaa有三种,后面的aaa有三种,所以一共应该是有9种情况. 可以考虑成3*3=9 如果你考虑分块去相乘的话,那么恭喜你,你GG了.因为这样写非常复杂,而且非常难判断. 可以考虑下dp,因为注意到,它每个单词只有

[字符串hash] hdu 4821 String

题意: 给你M,L,再给一个串str 任意截取M*L长度的连续子串 再把这个子串分成M份长度为L的连续串 使得这M份互不相同 问有几种截取方法 思路: 考虑到子串是否相等,就运用字符串hash 用到map判重和割补的办法优化 代码: #include"cstdlib" #include"cstdio" #include"cstring" #include"cmath" #include"queue" #in

HDOJ--4821--String【字符串hash】

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821 题意:给一个字符串,选m个长度为l的子串组成新的串,要求这m个子串互不相同,问有多少种组合. 字符串hash题目,以前没做过,做这道之前还用bkdrhash做了两道简单的题目,POJ1200和HDU1800. 用base数组记录乘了几个seed,base[i]表示seed^i,这个数组在之后计算子串hash值的时候会用到,先预处理一遍节省时间. 如果字符串从前往后hash,则hash[ i ] -

【二分答案+智障的字符串hash】BZOJ2946-[Poi2000]公共串(Ranklist倒一达成!!!!!)【含hash知识点】

[题目大意] 给出几个由小写字母构成的单词,求它们最长的公共子串的长度. [字符串hash的小笔记] hash[i]=(hash[i-1]*p+idx(s[i]))%mod,idx为映射值,一般a..z映射1..26: 习惯上,p取一个6到8位的素数即可,mod一般取大素数 1e9+7(1000000007)或1e9+9(1000000009). hash[i]=(hash[i-1]*p+idx(s[i]))%mod 表示第 i 个前缀的hash值,是一个hash的前缀和,那么,要求S[l…r]