• 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:
    ", ++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
    ", 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 }
  • 相关阅读:
    技术分享 | web自动化测试文件上传与弹框处理
    技术分享 | web 控件的交互进阶
    技术分享 | web自动化测试执行 JavaScript 脚本
    技术分享 | 想做App测试就一定要了解的App结构
    技术分享 | 网页 frame 与多窗口处理
    机械键盘转蓝牙键盘
    手动验证 TLS 证书
    因为一句话,秒懂二叉树旋转
    【Linux】本地虚拟机使用ssh服务
    查看SO KO 执行程序相关信息命令
  • 原文地址:https://www.cnblogs.com/gj-Acit/p/4678576.html
Copyright © 2020-2023  润新知