您的位置:首页 > 其它

HDU 3973 AC's String 字符串哈希

2015-07-26 20:02 183 查看
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查找,那么问题就解决了。

//#pragma comment(linker, "/STACK:1677721600")
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <vector>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
#define INF 0x3f3f3f3f
#define inf (-((LL)1<<40))
#define lson k<<1, L, (L + R)>>1
#define rson k<<1|1,  ((L + R)>>1) + 1, R
#define mem0(a) memset(a,0,sizeof(a))
#define mem1(a) memset(a,-1,sizeof(a))
#define mem(a, b) memset(a, b, sizeof(a))
#define FIN freopen("in.txt", "r", stdin)
#define FOUT freopen("out.txt", "w", stdout)
#define rep(i, a, b) for(int i = a; i <= b; i ++)
#define dec(i, a, b) for(int i = a; i >= b; i --)

template<class T> T MAX(T a, T b) { return a > b ? a : b; }
template<class T> T MIN(T a, T b) { return a < b ? a : b; }
template<class T> T GCD(T a, T b) { return b ? GCD(b, a%b) : a; }
template<class T> T LCM(T a, T b) { return a / GCD(a,b) * b;    }

//typedef __int64 LL;
typedef long long LL;
const int MAXN = 100000 + 100;
const int MAXM = 110000;
const double eps = 1e-8;
LL MOD = 1000000007;

const LL P = 33;

int t, n, m, cas = 0, l, r;
LL mi[MAXN];
char str[2000001], ch;
map<LL, int>mp;

void init() {
mi[0] = 1;
rep (i, 1, MAXN - 1) {
mi[i] = mi[i - 1] * P;
}
}

int toNum(char ch) {
return ch - 'a' + 1;
}

LL Hash() {
LL ans = 0;
int len = strlen(str);
dec (i, len - 1, 0) {
ans = ans * P + toNum(str[i]);
}
return ans;
}

struct SegTree {
LL ma[MAXN << 2];

void update(int k, int L, int R, int p, int v) {
if(L == R) { ma[k] = v; return ; }
int mid = (L + R) >> 1;
if(mid >= p) update(lson, p, v);
else update(rson, p, v);
ma[k] = ma[k << 1] + ma[k << 1 | 1] * mi[mid - L + 1];
}

LL query(int k, int L, int R, int l, int r) {
if(r < L || R < l) return 0;
if(l <= L && R <= r) return ma[k];
LL le = query(lson, l, r), ri = query(rson, l, r);
int mid = (L + R) >> 1;
return le + ri * mi[max(mid - max(L, l) + 1, 0)];
}

}st;

int main()
{
//    FIN;
init();
cin >> t;
while(t--) {
mp.clear();
mem0(st.ma);
scanf("%d%*c", &n);
rep (i, 0, n - 1) {
scanf("%s", str);
mp[Hash()] = 1;
}
scanf("%s", str);
int len = strlen(str);
rep (i, 0, len - 1) {
st.update(1, 1, len, i + 1, toNum(str[i]));
}
printf("Case #%d:\n", ++cas);
scanf("%d%*c", &m);
while(m --) {
scanf("%c", &ch);
if(ch == 'Q') {
scanf("%d %d%*c", &l, &r);
printf("%s\n", mp[st.query(1, 1, len, ++l, ++r)] ? "Yes" : "No");
}
else {
scanf("%d %c%*c", &l, &ch);
st.update(1, 1, len, ++l, toNum(ch));
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: