题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3973 , 线段树 + 字符哈希,好题。
又学了一种新的哈希方法,hhhh~
解法:
想法是用P进制的数来表示一个字符串,由于可能数太大,所以就将转换成是十进制后的数模long long的最大值,这样虽然也有可能冲突,但是概率会非常小。这里的P可以随意取一个素数(我取的是31)。
先用上面提到的哈希方法将W集合中的字符串都转成十进制数存在数组中,然后进行排序;每一次询问时候,将询问区间的子串转成十进制后二分查找是否在W集合中即可。
思路虽然简单,但是实现起来还是比较麻烦,尤其是有很多细节需要注意。
#include <iostream> #include <cstdio> #include <cmath> #include <queue> #include <vector> #include <string> #include <string.h> #include <algorithm> using namespace std; #define LL __int64 #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 const int maxn = 100000 + 20; const int p = 31; char str[2000020]; LL Hash[maxn << 2] , P[maxn]; LL W[10000 + 5]; void init() { P[0] = 1; for(int i = 1 ; i <= maxn ; i++) P[i] = P[i - 1] * p; } LL calhash(char str[]) { LL sum = 0; for(int i = 0 ; str[i] != '