hdu 3973 字串hash+線段樹
http://acm.hdu.edu.cn/showproblem.php?pid=3973
Problem Description
You are given some words {Wi}. Then our stupid AC will give you a very long string S. AC is stupid and always wants to know whether one substring from S exists in the given words {Wi} .
For example, S = "abcd", and the given words {Wi} = {"bc", "ad", "dd"}. Then Only S[2..3] = "bc" exists in the given words. (In this problem, the first element of S has the index "0".)
However, this is toooooooooooo easy for acmers ! The stupid and evil AC will now change some letters in S. So could you solve this problem now?
For example, S = "abcd", and the given words {Wi} = {"bc", "ad", "dd"}. Then Only S[2..3] = "bc" exists in the given words. (In this problem, the first element of S has the index "0".)
However, this is toooooooooooo easy for acmers ! The stupid and evil AC will now change some letters in S. So could you solve this problem now?
Input
The first line is one integer T indicates the number of the test cases. (T <=20)
Then for every case, there is one integer n in the first line indicates the number of the given words(The size of the {Wi}) . Then n lines has one string which only has 'a'- 'z'. (1 <= n <= 10000, sigma|Wi| <= 2000000) .
Then one line has one string S, here |S| <= 100000.
Then one integer m, indicating the number of operations. (1 <= m <= 100000)
Then m lines , each line is the operation:
(1)Q L R , tell AC whether the S[L..R] exists in the given strings ;
(2)C X Y , chang S[X] to Y, here Y : 'a'-'z' .
Then for every case, there is one integer n in the first line indicates the number of the given words(The size of the {Wi}) . Then n lines has one string which only has 'a'- 'z'. (1 <= n <= 10000, sigma|Wi| <= 2000000) .
Then one line has one string S, here |S| <= 100000.
Then one integer m, indicating the number of operations. (1 <= m <= 100000)
Then m lines , each line is the operation:
(1)Q L R , tell AC whether the S[L..R] exists in the given strings ;
(2)C X Y , chang S[X] to Y, here Y : 'a'-'z' .
Output
First output “Case #idx:” in a single line, here idx is the case number count from 1.Then for each "Q" operation, output "Yes" if S[L..R] exists in the given strings, otherwise output "No".
Sample Input
1
2
ab
ioc
ipcad
6
Q 0 2
Q 3 4
C 1 o
C 4 b
Q 0 2
Q 3 4
Sample Output
Case #1:
No
No
Yes
Yes
/**
hdu 3973 線段樹單點更新區間求值+字串hash
題目大意:給定多個字串,然後給定一個大串,對該串進行單點更新和區間查詢,查詢的區間子串是不是在已知的字串中出現
解題思路:對字串進行hash處理採用線段樹來進行更新,用set存放字串的雜湊值。至於怎麼雜湊和大白書上的思路差不多隻是這裡是表示的字首
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <set>
using namespace std;
const int maxn=100010;
const int seed=31;
typedef unsigned long long LL;
struct note
{
int l,r;
LL hashes;
}tree[maxn*4];
char str[2000100];
LL Hash[maxn];
int n;
void init()
{
Hash[0]=1;
for(int i=1;i<maxn;i++)
{
Hash[i]=Hash[i-1]*seed;
}
}
LL get_hash()
{
int len=strlen(str);
LL sum=0;
for(int i=0;i<len;i++)
sum=sum*seed+str[i]-'a'+1;
return sum;
}
void build(int l,int r,int root)
{
tree[root].l=l;
tree[root].r=r;
if(l==r)
{
tree[root].hashes=str[l]-'a'+1;
return;
}
int mid=(l+r)/2;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
tree[root].hashes=tree[root<<1].hashes*Hash[r-mid]+tree[root<<1|1].hashes;
}
void update(int l,int root)
{
if(tree[root].l==tree[root].r)
{
tree[root].hashes=str[l]-'a'+1;
return;
}
int mid=(tree[root].l+tree[root].r)>>1;
if(l<=mid) update(l,root<<1);
else update(l,root<<1|1);
tree[root].hashes=tree[root<<1].hashes*Hash[tree[root].r-mid]+tree[root<<1|1].hashes;
}
LL query(int l,int r,int root)
{
// printf("**\n");
if(tree[root].l==l&&tree[root].r==r)
return tree[root].hashes;
int mid=(tree[root].r+tree[root].l)>>1;
if(r<=mid)return query(l,r,root<<1);
else if(l>mid)return query(l,r,root<<1|1);
return query(l,mid,root<<1)*Hash[r-mid]+query(mid+1,r,root<<1|1);
}
int main()
{
int T,tt=0;
init();
scanf("%d",&T);
while(T--)
{
printf("Case #%d:\n",++tt);
scanf("%d",&n);
set<LL>mp;
for(int i=0;i<n;i++)
{
scanf("%s",str);
mp.insert(get_hash());
}
scanf("%s",str);
int len=strlen(str);
build(0,len-1,1);
int q;
scanf("%d",&q);
for(int i=1;i<=q;i++)
{
char c[5];
scanf("%s",c);
if(c[0]=='C')
{
int a;
char b[10];
scanf("%d%s",&a,b);
str[a]=b[0];
update(a,1);
}
else
{
int l,r;
scanf("%d%d",&l,&r);
if(mp.find(query(l,r,1))!=mp.end())
printf("Yes\n");
else
printf("No\n");
}
}
}
return 0;
}
相關文章
- hdu 1754 I Hate It (線段樹)
- Transformation HDU - 4578線段樹綜合操作ORM
- hdu 1754 【線段樹/RMQ】I Hate ItMQ
- hdu4288 離線處理線段樹
- hdu 4836 The Query on the Tree(線段樹or樹狀陣列)陣列
- HDU 1754 I Hate It 線段樹入門
- HDU 1556 Color the ball(線段樹|樹狀陣列)陣列
- HDU 1754 I Hate It (線段樹 區間最值)
- hdu 1394 Minimum Inversion Number 【線段樹查詢】
- HDU 1556 Color the ball 線段樹入門題
- HDU 1698 Just a Hook (線段樹區間更新)Hook
- hdu 2665 可持久化線段樹求區間第K大值(函式式線段樹||主席樹)持久化函式
- HDU 3333 Turing Tree(線段樹+離線操作)
- HDU 3074 Multiply game(線段樹 單點更新)GAM
- (hdu 1754) I Hate It(線段樹基礎,單點更新)
- 【BZOJ3207】花神的嘲諷計劃Ⅰ hash+可持久化線段樹持久化
- 線段樹 hate it
- 線段樹模板
- 01 線段樹
- HDU 1166 敵兵佈陣 線段樹入門題目
- HDU1754 I Hate It 【線段樹基礎:點修改+區間查詢】
- (hdu 1166)敵兵佈陣(線段樹入門,單點更新)
- 線段樹筆記筆記
- 線段樹入門
- 權值線段樹
- 線段樹(毒瘤)總結
- 線段樹模板總結
- 深入理解線段樹
- 線段樹入門理解
- 第二課——線段樹
- HDU1698 Just a Hook【線段樹基礎:區間修改+區間查詢】Hook
- 線段樹 - 多組圖帶你從頭到尾徹底理解線段樹
- 資料結構之樹( 線段樹,字典樹)資料結構
- HDU 5469 Antonidas(樹上的字串匹配/搜尋)字串匹配
- 資料結構-線段樹資料結構
- 關於線段樹基礎
- 淺談線段樹(Segment Tree)
- [18/03/24] 線段樹模板