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;
}
原文地址:https://www.cnblogs.com/KirinSB/p/9493248.html