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?
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' .
1 2 ab ioc ipcad 6 Q 0 2 Q 3 4 C 1 o C 4 b Q 0 2 Q 3 4
Case #1: No No Yes Yes
//
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
using namespace std;
const int maxn=110000;
//字符串HASH 重复概率很小
//Hash(s)=sigma((s[i]-'a'+1)*27^(i))%mod;
const int mod=1000000007;
int bit[maxn+10];
map<int,bool> g;//使用前要清空
void initHashStr()
{
bit[0]=1;
for(int i=1;i<=maxn;i++)bit[i]=((long long)bit[i-1]*27)%mod;
}
//返回true 表示已经存在,false 表示还没有此串,可以添加
bool getHashStr(char* str)
{
int cnt=0;
for(int i=0;str[i];i++)
{
cnt=((long long)cnt+(long long)(str[i]-'a'+1)*bit[i])%mod;
}
cnt=((long long)cnt*bit[maxn])%mod;//important
if(g[cnt]) return true;
g[cnt]=true;
return false;
}
//查询子串是否是模式串 可以修改
//树状数组 sum[i]=sigma((s[i]-'a'+1)*bit[i])%mod;
//子串 hash[s]=(sum[i]-sum[j-1])/bit[j];
//这里将/bit[j]都乘以bit[maxn],可以在字符串hash中先初始化
char str[maxn+1];
int len;
int c[maxn+10];
int lowbit(int x){return x&(-x);}
void add(int x,int val)
{
for(int i=x;i<=len;i+=lowbit(i))
{
c[i]=(((long long)c[i]+val)%mod+mod)%mod;//important 防止出现负数
}
}
int getsum(int x)
{
int cnt=0;
for(int i=x;i>=1;i-=lowbit(i))
{
cnt=((long long)cnt+c[i])%mod;
}
return cnt;
}
int main()
{
//freopen("in","r",stdin);
//freopen("out.txt","w",stdout);
initHashStr();
int ci,pl=1;scanf("%d",&ci);
while(ci--)
{
g.clear();
int n;scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%s",str);//模式串
getHashStr(str);//对模式串hash
}
scanf("%s",str);//母串
len=strlen(str);
memset(c,0,sizeof(c));
for(int i=0;str[i];i++)
{
int cnt=((long long)(str[i]-'a'+1)*bit[i])%mod;
add(i+1,cnt);
}
printf("Case #%d:\n",pl++);
int q;scanf("%d",&q);
//树状数组从1开始
while(q--)
{
char ch[2],cr[2];int x,y;
scanf("%s",ch);
if(ch[0]=='Q')
{
scanf("%d%d",&x,&y);//查询[x,y]是否出现在模式串中
int cnt=(((long long)getsum(y+1)-getsum(x))%mod+mod)%mod;
cnt=((long long)cnt*bit[maxn-x])%mod;
if(g[cnt]) printf("Yes\n");
else printf("No\n");
}
else
{
scanf("%d%s",&x,cr);
int cnt=((long long)(cr[0]-str[x])*bit[x])%mod;
add(x+1,cnt);
str[x]=cr[0];
}
}
}
return 0;
}