题目链接: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. Ubuntu16.4下安装Chrome浏览器以及Chromedriver

    一.Chrome浏览器的安装 对于谷歌Chrome32位版本,使用如下链接: wget https://dl.google.com/linux/direct/google-chrome-stable_ ...

  2. [Windows]获取系统版本号

    1 string GetMainProgInfo() 2 { 3 string strRet; 4 TCHAR szPath[MAX_PATH]; 5 GetModuleFileName(NULL,s ...

  3. 前端编码规范 -- html篇

    文档类型 推荐使用 HTML5 的文档类型申明: <!DOCTYPE html> (建议使用 text/html 格式的 HTML.避免使用 XHTML.XHTML 以及它的属性,比如 a ...

  4. 51nod 1781 Pinball(线段树)

    题面 Pinball的游戏界面由m+2行.n列组成.第一行在顶端.一个球会从第一行的某一列出发,开始垂直下落,界面上有一些漏斗,一共有m个漏斗分别放在第2~m+1行,第i个漏斗的作用是把经过第i+1行 ...

  5. 初识Scrapy之再续火影情缘

    前言Scrapy框架之初窥门径1 Scrapy简介2 Scrapy安装3 Scrapy基础31 创建项目32 Shell分析4 Scrapy程序编写41 Spiders程序测试42 Items编写43 ...

  6. Ubuntu 防火墙IP转发做NAT,内网集群共享网络(简单)

    服务器架构: 系统: Ubuntu 16.04 x64 使用自带防火墙 UFW 操作: 在有公网的服务器上,进行防火墙基本操作开启自己所需业务的端口,并按下方设置启动NAT: 其他内网机器修改网关或者 ...

  7. 需要命名空间管理器或 XsltContext。此查询具有前缀、变量或用户定义的函数 及 多属性节点查询

    第一个问题, 1. 首先需要引入命名空间, 2. 其次,在用xpath查找结点时,在selectNodes等方法中再次带入命名空间 如 XmlDocument doc = new XmlDocumen ...

  8. Webpack打包时警告 - Critical dependency: the request of a dependency is an expression

    关于解决 [Webpack] Critical dependency: the request of a dependency is an expression ------------------- ...

  9. 如何在html文件中导入header、footer等

    1.include是php函数,所以确实需要转化成.php文件--(其实除了用php,html都有自带的引入方法)2.html转化为php文件很简单,直接改一下后缀名就可以了--(如:index.ht ...

  10. POJ1010 Stamps

    题目来源:http://poj.org/problem?id=1010 题目大意: 某邮局要设计新的邮资管理软件,依据顾客的需要和现有的面值给顾客分派邮票. 该邮局有很多顾客是集邮爱好者.这些人希望得 ...