HDU 3973 AC's String 字符串哈希

HDU 3973

通过哈希函数将一个字符串转化为一个整数,通过特定的方式可以使得这个哈希值几乎没有冲突(这就是关键之处,几乎没有视为没有= =!, 其实也可以考虑实现哈希冲突时的处理,只是这道题没必要而已),然后使用线段树维护修改后的哈希值。

因为输入的字符串只有26个,考虑使用一个大于等于26的素数p作为进制,然后将原串转化为一个p进制的数mod 2^63(也相当于自然溢出),然后这个数存入map中,然后使用线段树维护长串区间的哈希值,hash[l, r]表示将区间[l, r]的字符串转化为p进制数(哈希过程)的结果,那么对于当前区间[l, r]的两个子区间[l, m]与[m + 1, r]:

hash[l, r] = hash[l, m] + hash[m + 1, r] * (p ^ (m - l + 1))

使用线段树动态维护,查询区间的hash值,使用map查找,那么问题就解决了。

  1 //#pragma comment(linker, "/STACK:1677721600")
  2 #include <map>
  3 #include <set>
  4 #include <stack>
  5 #include <queue>
  6 #include <cmath>
  7 #include <ctime>
  8 #include <vector>
  9 #include <cstdio>
 10 #include <cctype>
 11 #include <cstring>
 12 #include <cstdlib>
 13 #include <iostream>
 14 #include <algorithm>
 15 using namespace std;
 16 #define INF 0x3f3f3f3f
 17 #define inf (-((LL)1<<40))
 18 #define lson k<<1, L, (L + R)>>1
 19 #define rson k<<1|1,  ((L + R)>>1) + 1, R
 20 #define mem0(a) memset(a,0,sizeof(a))
 21 #define mem1(a) memset(a,-1,sizeof(a))
 22 #define mem(a, b) memset(a, b, sizeof(a))
 23 #define FIN freopen("in.txt", "r", stdin)
 24 #define FOUT freopen("out.txt", "w", stdout)
 25 #define rep(i, a, b) for(int i = a; i <= b; i ++)
 26 #define dec(i, a, b) for(int i = a; i >= b; i --)
 27
 28 template<class T> T MAX(T a, T b) { return a > b ? a : b; }
 29 template<class T> T MIN(T a, T b) { return a < b ? a : b; }
 30 template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
 31 template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }
 32
 33 //typedef __int64 LL;
 34 typedef long long LL;
 35 const int MAXN = 100000 + 100;
 36 const int MAXM = 110000;
 37 const double eps = 1e-8;
 38 LL MOD = 1000000007;
 39
 40 const LL P = 33;
 41
 42 int t, n, m, cas = 0, l, r;
 43 LL mi[MAXN];
 44 char str[2000001], ch;
 45 map<LL, int>mp;
 46
 47 void init() {
 48     mi[0] = 1;
 49     rep (i, 1, MAXN - 1) {
 50         mi[i] = mi[i - 1] * P;
 51     }
 52 }
 53
 54 int toNum(char ch) {
 55     return ch - ‘a‘ + 1;
 56 }
 57
 58 LL Hash() {
 59     LL ans = 0;
 60     int len = strlen(str);
 61     dec (i, len - 1, 0) {
 62         ans = ans * P + toNum(str[i]);
 63     }
 64     return ans;
 65 }
 66
 67 struct SegTree {
 68     LL ma[MAXN << 2];
 69
 70     void update(int k, int L, int R, int p, int v) {
 71         if(L == R) { ma[k] = v; return ; }
 72         int mid = (L + R) >> 1;
 73         if(mid >= p) update(lson, p, v);
 74         else update(rson, p, v);
 75         ma[k] = ma[k << 1] + ma[k << 1 | 1] * mi[mid - L + 1];
 76     }
 77
 78     LL query(int k, int L, int R, int l, int r) {
 79         if(r < L || R < l) return 0;
 80         if(l <= L && R <= r) return ma[k];
 81         LL le = query(lson, l, r), ri = query(rson, l, r);
 82         int mid = (L + R) >> 1;
 83         return le + ri * mi[max(mid - max(L, l) + 1, 0)];
 84     }
 85
 86 }st;
 87
 88 int main()
 89 {
 90 //    FIN;
 91     init();
 92     cin >> t;
 93     while(t--) {
 94         mp.clear();
 95         mem0(st.ma);
 96         scanf("%d%*c", &n);
 97         rep (i, 0, n - 1) {
 98             scanf("%s", str);
 99             mp[Hash()] = 1;
100         }
101         scanf("%s", str);
102         int len = strlen(str);
103         rep (i, 0, len - 1) {
104             st.update(1, 1, len, i + 1, toNum(str[i]));
105         }
106         printf("Case #%d:\n", ++cas);
107         scanf("%d%*c", &m);
108         while(m --) {
109             scanf("%c", &ch);
110             if(ch == ‘Q‘) {
111                 scanf("%d %d%*c", &l, &r);
112                 printf("%s\n", mp[st.query(1, 1, len, ++l, ++r)] ? "Yes" : "No");
113             }
114             else {
115                 scanf("%d %c%*c", &l, &ch);
116                 st.update(1, 1, len, ++l, toNum(ch));
117             }
118         }
119     }
120     return 0;
121 }

HDU 3973 AC's String 字符串哈希

时间: 2024-08-06 11:35:48

HDU 3973 AC's String 字符串哈希的相关文章

HDU - 3973 AC&#39;s String(Hash+线段树)

http://acm.hdu.edu.cn/showproblem.php?pid=3973 题意 给一个词典和一个主串.有两种操作,查询主串某个区间,问这主串区间中包含多少词典中的词语.修改主串某一位置的字符. 分析 题目要求区间查询,和单点更新,那么最先想到的应该是线段树.可字符串怎么利用线段树呢?用hash!首先将词典按规则hash后放入map,然后将主串的hash值放置入线段树中.问题来了,怎么更新结点的hash值呢?假如现在我们知道了s[l...mid]和s[mid+1...r]的ha

HDU 3973 AC&#39;s String (substr 强行匹配)

AC's String Time Limit: 30000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1127    Accepted Submission(s): 316 Problem Description You are given some words {Wi}. Then our stupid AC will give you a very long

[HDU 4821] String (字符串哈希)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4821 题目大意:给你M,L两个字母,问你给定字串里不含M个长度为L的两两相同的子串有多少个? 哈希+枚举 我就是不会枚举这样的,这次涨姿势了. 每次枚举起点,然后就能枚举全部的. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #inclu

hdu 4300 Clairewd’s message 字符串哈希

Clairewd’s message Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 10376    Accepted Submission(s): 3709 Problem Description Clairewd is a member of FBI. After several years concealing in BUPT,

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 杭州现场赛:每个片段字符串哈希比较

I - String Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Status Practice HDU 4821 Description Given a string S and two integers L and M, we consider a substring of S as "recoverable" if and only if (i) I

hdu 2296 aC自动机+dp(得到价值最大的字符串)

Ring Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3180    Accepted Submission(s): 1033 Problem Description For the hope of a forever love, Steven is planning to send a ring to Jane with a rom

hdu 4850 Wow! Such String!(字符串处理,yy)

题目 参考了博客http://blog.csdn.net/u013368721/article/details/37575165 //用visit[26][26][26][26]来判断新家新区的子母河前三个组合而成的4个字符的串是否和之前的重复. //再加上最初三个字符,所以,总共有26*26*26*26+3的长度. /* //以下复制自博客http://blog.csdn.net/u013368721/article/details/37575165 题目大意:给你一个整数n,让你输出一个字符

HDU 5842 Lweb and String(Lweb与字符串)

HDU 5842 Lweb and String(Lweb与字符串) Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)   Problem Description - 题目描述 Lweb has a string S. Oneday, he decided to transform this string to a new sequence. You need help him