Problem_A
Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64uDescription
度熊手上有一本字典存储了大量的单词,有一次,他把所有单词组成了一个很长很长的字符串。现在麻烦来了,他忘记了原来的字符串都是什么,神奇的是他竟然记得原来那些字符串的哈希值。一个字符串的哈希值,由以下公式计算得到:
H(s)=prod_{i=1}^{ileq len(s)}(S_{i}-28) (mod 9973)
S_{i}代表 S[i] 字符的 ASCII 码。
请帮助度熊计算大字符串中任意一段的哈希值是多少。
H(s)=prod_{i=1}^{ileq len(s)}(S_{i}-28) (mod 9973)
S_{i}代表 S[i] 字符的 ASCII 码。
请帮助度熊计算大字符串中任意一段的哈希值是多少。
Input
多组测试数据,每组测试数据第一行是一个正整数N,代表询问的次数,第二行一个字符串,代表题目中的大字符串,接下来N行,每行包含两个正整数a和b,代表询问的起始位置以及终止位置。
1leq Nleq 1,000
1leq len(string)leq 100,000
1leq a,bleq len(string)
1leq Nleq 1,000
1leq len(string)leq 100,000
1leq a,bleq len(string)
Output
对于每一个询问,输出一个整数值,代表大字符串从 a 位到 b 位的子串的哈希值。
Sample Input
2
ACMlove2015
1 11
8 10
1
testMessage
1 1
Sample Output
6891 9240 88
//这题用数学公式做,貌似很简单,但是我不会,用线段树做的,也比较快嘛。187ms AC
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 struct Tree 7 { 8 int hx; 9 int l,r; 10 }tree[300000]; 11 12 char str[100005]; 13 14 int build_tree(int left,int right,int k) 15 { 16 tree[k].l=left; 17 tree[k].r=right; 18 19 if (left==right) //到子节点 20 { 21 tree[k].hx=str[left-1]-28; 22 return tree[k].hx; 23 } 24 25 int mid=(left+right)/2; 26 27 tree[k].hx=( build_tree(left,mid,2*k) * build_tree(mid+1,right,2*k+1))%9973; 28 return tree[k].hx; 29 } 30 31 int find(int left,int right,int k) 32 { 33 if( left==tree[k].l && right==tree[k].r ) 34 return tree[k].hx; 35 36 int mid=(tree[k].l+tree[k].r)/2; 37 38 if (left>mid) return find(left,right,2*k+1); 39 if (right<=mid) return find(left,right,2*k); 40 41 return ( find(left,mid,2*k) * find(mid+1,right,2*k+1) )%9973; 42 } 43 44 int main() 45 { 46 int N; 47 int len,a,b; 48 while (scanf("%d",&N)!=EOF) 49 { 50 scanf("%s",str); 51 len=strlen(str); 52 build_tree(1,len,1); 53 54 while (N--) 55 { 56 scanf("%d%d",&a,&b); 57 printf("%d ",find(a,b,1)); 58 } 59 60 } 61 return 0; 62 }