题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3973 , 线段树 + 字符哈希,好题。

  又学了一种新的哈希方法,hhhh~


解法:

  想法是用P进制的数来表示一个字符串,由于可能数太大,所以就将转换成是十进制后的数模long long的最大值,这样虽然也有可能冲突,但是概率会非常小。这里的P可以随意取一个素数(我取的是31)。

  先用上面提到的哈希方法将W集合中的字符串都转成十进制数存在数组中,然后进行排序;每一次询问时候,将询问区间的子串转成十进制后二分查找是否在W集合中即可。

   思路虽然简单,但是实现起来还是比较麻烦,尤其是有很多细节需要注意。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <queue>
#include <vector>
#include <string>
#include <string.h>
#include <algorithm>
using namespace std;
#define LL __int64
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = + ;
const int p = ;
char str[];
LL Hash[maxn << ] , P[maxn];
LL W[ + ];
void init()
{
P[] = ;
for(int i = ; i <= maxn ; i++)
P[i] = P[i - ] * p;
}
LL calhash(char str[])
{
LL sum = ;
for(int i = ; str[i] != '\0' ; i++) {
sum = sum * p + str[i] - 'a' + ;
}
return sum;
}
int binary_search(int l , int r , LL a[] , LL x)
{
int m = (l + r) >> ;
while(l <= r) {
if(a[m] == x)
return m;
if(a[m] > x)
r = m - ;
if(a[m] < x)
l = m + ;
m = (l + r) >> ;
}
return -;
}
void PushUp(int l , int r , int rt)
{
int m = (l + r) >> ;
Hash[rt] = Hash[rt << ] * P[r - m] + Hash[rt << | ];
}
void build(int l , int r , int rt)
{
if(l == r) {
Hash[rt] = str[r] - 'a' + ;
return;
}
int m = (l + r) >> ;
build(lson);
build(rson);
PushUp(l , r , rt);
}
void update(int x , int l , int r , int rt)
{
if(l == r) {
Hash[rt] = str[x] - 'a' + ;
return;
}
int m = (l + r) >> ;
if(x > m)
update(x , rson);
else
update(x , lson);
PushUp(l , r , rt);
}
LL query(int L , int R , int l , int r , int rt)
{
if(L <= l && R >= r) {
return Hash[rt];
}
int m = (l + r) >> ;
if(m < L)
return query(L , R , rson);
else if(m >= R)
return query(L , R , lson);
else
return query(L , m , lson) * P[R - m] + query(m + , R , rson);
}
int main()
{
int n , m , T;
char ch[] , s[];
init();
cin >> T;
for(int k = ; k <= T ; k++)
{
scanf("%d" , &n);
for(int i = ; i <= n ; i++) {
scanf("%s" , str);
W[i] = calhash(str);
}
sort(W + , W + n + );
scanf("%s" , str);
int len = strlen(str);
build( , len - , );
printf("Case #%d:\n" , k);
scanf("%d" , &m);
while(m--) {
scanf("%s" , ch);
if(ch[] == 'Q') {
int L , R;
scanf("%d %d" , &L , &R);
LL tmp = query(L , R , , len - , );
if(binary_search( , n , W , tmp) != -)
puts("Yes");
else
puts("No");
} else {
int x;
scanf("%d" , &x);
scanf("%s" , s);
str[x] = s[];
update(x , , len - , );
}
}
}
return ;
}

HDU3973 线段树 + 字符哈希的更多相关文章

  1. 【URAL 1989】 Subpalindromes(线段树维护哈希)

    Description You have a string and queries of two types: replace i'th character of the string by char ...

  2. CF213E Two Permutations 线段树维护哈希值

    当初竟然看成子串了$qwq$,不过老师的$ppt$也错了$qwq$ 由于子序列一定是的排列,所以考虑插入$1$到$m$到$n-m+1$到$n$; 如何判断呢?可以用哈希$qwq$: 我们用线段树维护哈 ...

  3. [bzoj2124]等差子序列——线段树+字符串哈希

    题目大意 给一个1到N的排列\(A_i\),询问是否存在\(p_i\),\(i>=3\),使得\(A_{p_1}, A_{p_2}, ... ,A_{p_len}\)是一个等差序列. 题解 显然 ...

  4. 51Nod1553 周期串查询 字符串 哈希 线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1553.html 题目传送门 - 51Nod1553 题意 有一个串只包含数字字符.串的长度为n,下标 ...

  5. 线段树+哈希【CF580E】Kefa and Watch

    线段树+哈希[CF580E]Kefa and Watch Description \(n\)个数的字符串,\(m + k\)个操作 1 l r k把\(l - r\)赋值为\(k\) 2 l r d询 ...

  6. 【Vjudge】P1989Subpalindromes(线段树)

    题目链接 水题一道,用线段树维护哈希值,脑补一下加减乱搞搞……注意细节就过了 一定注意细节…… #include<cstdio> #include<cstdlib> #incl ...

  7. 【线段树哈希】「Balkan OI 2016」Haker

    1A海星 题目大意 给你一个长度为 $n$ ,由小写字母构成的字符串 $S$ 和 $Q$ 个操作,每个操作是以下 3 种之一: 1 x y k :询问当前字符串从位置 $x$ 到 $y$ 的子串与从位 ...

  8. hdu3973 AC's String 线段树+字符串hash

    题目链接:http://icpc.njust.edu.cn/Problem/Hdu/3973/ 题意是:给出一个模式串,再给出一些串组成一个集合,操作分为两种,一种是替换模式串中的一个字符,还有一种是 ...

  9. N - Subpalindromes URAL - 1989 哈希+线段树

    N - Subpalindromes URAL - 1989 这个是一个哈希+线段树,这个题目也不算特别难,但是呢,还比较有意思. 这个题目给你两个操作,一个是回答l~r 区间是不是回文,一个是对一个 ...

随机推荐

  1. 初始Java虚拟机

    Java虚拟机内存模型(Java运行在虚拟机之上,虚拟机帮Java屏蔽底层的指令集,让Java能够跨平台运行) 内存模型以及分区,需要详细到每个区放什么? 方法区(method area): 方法信息 ...

  2. n皇后问题_回溯法

    具体问题如下图 先看一下4*4的回溯过程 程序结束条件: 一组解:设标志,找到一解后更改标志,以标志做为结束循环的条件. 所有解:k=0 判断约束函数判断第k个后能不能放在x[k]处 两个皇后不能放在 ...

  3. Linux基础学习(一)

    前言:这个学习笔记是为了督促自己能够更好的学习Linux的有关知识. 参考书目 鸟哥的linux私房菜 Chapter 1:入门建议 新手建议:重点 基础一定一定要学好 那么什么是基础呢? 先从Lin ...

  4. 设计模式实战研磨 ——第1篇 UML环境搭建

    starUML是开源的基于统一模式语言与模式驱动开发的平台,前身是Plastic,从1996年开始开发.1998年开始,Plastic转变为UML建模工具.2005年改名为StarUML,最新版本St ...

  5. PAT甲级——1093 Count PAT's (逻辑类型的题目)

    本文同步发布在CSDN:https://blog.csdn.net/weixin_44385565/article/details/93389073 1093 Count PAT's (25 分)   ...

  6. IPv6邻居发现协议

    IPv6邻居发现协议 邻居发现协议NDP 邻居发现协议NDP(Neighbor Discovery Protocol)是IPv6协议体系中一个重要的基础协议.邻居发现协议替代了IPv4的ARP(Add ...

  7. POJ1047 Round and Round We Go

    题目来源:http://poj.org/problem?id=1047 题目大意: 有一些整数具有这样的性质:它的位数为n,把它和1到n的任意一个整数相乘结果的数字会是原数字的一个“环”.说起来比较抽 ...

  8. Windows下搭建QT环境

    必须软件 qt-windows-opensource-5.1.1-msvc2010-x86-offline qt-vs-addin-1.2.2-opensource支持vs2008.2010.2012 ...

  9. vi 编辑器的复制

    v 进入可视化模式,y  复制选中区域,p粘贴 Ctrl + v 块模式 yy 复制当前行

  10. windows下apache服务器的下载,安装,配置

    1.进行apache官网->Download->Files for Microsoft Windows->ApacheHaus,然后选择合适的版本下载 2.将下载下来的压缩包解压到合 ...