zoukankan      html  css  js  c++  java
  • FZU 2280 Magic(字符串Hash)题解

    题意:给你n个字符串,每个字符串有一个值w,有q次询问,一共两种操作:一是“1 x y”表示把第x个串的w变为y;二是“2 x”,输出第x个串能放几次魔法。放魔法的条件是这样:用串x放魔法,如果在1~n个串中,一个串的w不超过x的w并且x是这个串的后缀,则算放了一次魔法。

    思路:用Hash每个串,记录w,查询时遍历每个串的后缀是否和x相等并且wi <= wx。这里就是用到了字符串哈希的知识。

    参考:

    各种字符串Hash函数比较

    字符串系列(一)——伟大的字符串Hash

    代码:

    #include<cstdio>
    #include<set>
    #include<map>
    #include<cmath>
    #include<stack>
    #include<vector>
    #include<queue>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    #define ull unsigned long long
    using namespace std;
    const int maxn = 1000+10;
    const ull seed = 131;
    const int INF = 0x3f3f3f3f;
    char s[maxn][maxn];
    int w[maxn],len[maxn];
    ull hash[maxn][maxn];
    ull bin[maxn];  //seed的i次方自然溢出结果
    void init(){
        bin[0] = 1;
        for(int i = 1;i <= 1000;i++)    //预处理
            bin[i] = bin[i - 1] * seed;
    }
    void HASH(int n){
        for(int i = 1;i <= n;i++){  //每个串hash
            hash[i][0] = 0;
            for(int j = 1;j <= len[i];j++){
                hash[i][j] = hash[i][j - 1] * seed + s[i][j] - 'a';
            }
        }
    }
    inline ull getsuff(int i,int length){  //寻找子串hash值(此为后缀)
        int l = len[i] - length + 1,r = len[i];
        return (hash[i][r] - hash[i][l - 1] * bin[r - l + 1]);
    }
    int solve(int x,int n){
        int ans = 0;
        for(int i = 1;i <= n;i++){
            if(w[i] > w[x]) continue;
            if(len[i] < len[x]) continue;
            if(getsuff(i,len[x]) == hash[x][len[x]]){
                ans++;
            }
        }
        return ans;
    }
    int main(){
        int T;
        int n;
        init();
        scanf("%d",&T);
        while(T--){
            scanf("%d",&n);
            for(int i = 1;i <= n;i++){
                scanf("%s%d",s[i] + 1,&w[i]);
                len[i] = strlen(s[i] + 1);
            }
            HASH(n);
            int q;
            int o,x,y;
            scanf("%d",&q);
            while(q--){
                scanf("%d",&o);
                if(o == 1){
                    scanf("%d%d",&x,&y);
                    w[x] = y;
                }
                else{
                    scanf("%d",&x);
                    printf("%d
    ",solve(x,n));
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    请简单介绍spring支持的常用数据库事务传播属性和事务隔离级别
    Spring Bean的作用域
    成员变量与局部变量的区别
    递归与迭代
    方法参数的传递机制 ---- 值传递
    windows phone 动画 当子控件超出父控件返回时
    把dataset 输出到 excel
    代码段
    c++ 学习纪录
    做自己的代码生成器
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9493248.html
Copyright © 2011-2022 走看看