hdu 3973 字符串hash+线段树动态维护

7 篇文章 0 订阅
4 篇文章 0 订阅

AC's String

Time Limit: 30000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1091    Accepted Submission(s): 311


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?
 

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' .
 

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
 

Author
AekdyCoin
 

Source
 

Recommend
We have carefully selected several similar problems for you:   3972  3979  3978  3974  3976 
 

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
#include <stack>
#include <map>
using namespace std;
#define maxn 50001
#define mod 131111
#define M 20000
typedef unsigned int ui;

char s[100001];
ui base[2][100001]={{1,5},{1,7}};
struct hnode{
	ui val[2];
	int next;
	hnode(){}
	hnode(ui a, ui b) { val[0]=a;val[1]=b;}
	bool operator ==(const hnode &a) const
	{
		return val[0]==a.val[0]&&val[1]==a.val[1];
	}
};

int first[mod],tot;
hnode h[M];
void init()
{
	memset(first, -1, sizeof(first));
	tot=0;
}
void insert(hnode &a)
{
	int pos=a.val[0]%mod;
	h[tot]=a; h[tot].next=first[pos];
	first[pos]=tot++;
}

int find(hnode a)
{
	int pos=a.val[0]%mod;
	for(int i=first[pos]; i!=-1; i=h[i].next){
		if(h[i]==a)
			return 1;
	}
	return 0;
}

hnode tval[3*100001];
void build(int rt, int l, int r)
{
	int lc=rt<<1,rc=rt<<1|1;
	int m=(l+r)>>1;
	if(l==r){
		tval[rt]=hnode(s[l],s[l]);
		return;
	}

	build(lc, l, m);
	build(rc, m+1,r);
	for(int i=0; i<2; i++)
		tval[rt].val[i]=tval[lc].val[i]*base[i][r-m]+tval[rc].val[i];
}

void update(int rt, int l, int r, int ind)
{
	int lc=rt<<1,rc=rt<<1|1;
	int m=(l+r)>>1;
	if(l==r){
		tval[rt]=hnode(s[ind],s[ind]);
		return;
	}

	if(ind<=m) update(lc, l, m, ind);
	else update(rc, m+1, r, ind);
	for(int i=0; i<2; i++)
		tval[rt].val[i]=tval[lc].val[i]*base[i][r-m]+tval[rc].val[i];
}

hnode query(int rt, int l, int r, int ll, int rr)
{

	int lc=rt<<1,rc=rt<<1|1;
	int m=(l+r)>>1;
	if(ll<=l && rr>=r) return tval[rt];

	if(rr <= m)
		return query(lc, l, m, ll, rr);
	else if(ll > m)
		return query(rc, m+1, r, ll, rr);
	else{
		hnode a=query(lc, l, m, ll, m);
		hnode b=query(rc, m+1, r, m+1, rr);
		for(int i=0; i <2; i++)
			a.val[i]=a.val[i]*base[i][rr-m]+b.val[i];
		return a;
	}
}

int main()
{
	for(int i=0; i<2; i++)
		for(int j=2; j<=100000; j++)
			base[i][j]=base[i][1]*base[i][j-1];

	int t;
	scanf("%d",&t);
	int cas=1;
	while(t--){
        printf("Case #%d:\n", cas++);
		int n; scanf("%d", &n);
		hnode a;
		s[0]='a';
		init();
		for(int i=0; i<n; i++){
			scanf("%s", s+1);
			int len=strlen(s);
			a.val[0]=a.val[1]=0;
			for(int j=1; j<len; j++){
				for(int k=0; k<2; k++)
					a.val[k]=a.val[k]*base[k][1]+s[j];
			}
			insert(a);
			//cout << a.val[0] << " "<< a.val[1]<<endl;
		}

		scanf("%s", s+1);
		int len=strlen(s)-1;
		build(1, 1, len);
		int m; scanf("%d", &m);
		char op[3]; int l, r;
		while(m--){
			scanf("%s", op);
			if(op[0]=='Q'){
				scanf("%d%d", &l, &r);
				a=query(1, 1, len, l+1, r+1);
				//cout<<a.val[0]<<" "<<a.val[1]<<endl;
				if(find(a))
					printf("Yes\n");
				else printf("No\n");
			}
			else{
				scanf("%d%s", &l, op);
				l++;
				s[l]=op[0];
				update(1, 1, len, l);
			}
		}
	}
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值