HDU 3973 AC's String(hash+線段樹)

AC's String

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


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
 

題意:給n個字符串,再給一個母串,Q查詢母串的某個子串是否在字符串中,C改變母串對應位置的字符

題解:字符串hash成一個數,線段樹維護hash值,n個字符串用map保存,查詢時判斷即可。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <map>
#define lc idx<<1
#define rc idx<<1|1
#define lson l,mid,lc
#define rson mid+1,r,rc

using namespace std;

const int N = 100010;
const int o=31;
typedef long long ll;

ll p[N];
char s[N*20];
map<ll,bool>mp;
int n;

void init() {
    p[0]=1;
    for(int i=1; i<N; i++)p[i]=p[i-1]*o;
}

void Hash(char s[]) {
    int len=strlen(s);
    ll res=0;
    for(int i=0; i<len; i++) {
        res=res*o+s[i]-'a'+1;
    }
    mp[res]=true;
}

ll tree[N*4];

void push_up(int idx,int m) {
    tree[idx]=tree[lc]*p[m]+tree[rc];
}

void build(int l,int r,int idx) {
    if(l==r) {
        tree[idx]=s[l]-'a'+1;
        return;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    push_up(idx,r-mid);
}

void update(int l,int r,int idx,int x,int v) {
    if(l==r) {
        tree[idx]=v;
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)update(lson,x,v);
    else      update(rson,x,v);
    push_up(idx,r-mid);
}

ll query(int l,int r,int idx,int x,int y) {
    if(l>=x&&y>=r)
        return tree[idx];
    if(l<x&&r<x||(l>y&&r>y))return 0;
    int mid=(l+r)>>1;
    return query(rson,x,y)+query(lson,x,y)*p[max(min(y,r)-mid,0)];
}

int main() {
    //freopen("test.in","r",stdin);
    int t;
    init();
    cin>>t;
    int ca=1;
    while(t--) {
        scanf("%d",&n);
        mp.clear();
        for(int i=0; i<n; i++) {
            scanf("%s",s);
            Hash(s);
        }
        scanf("%s",s+1);
        n=strlen(s+1);
        build(1,n,1);
        int m;
        scanf("%d",&m);
        char c[2];
        int l,r;
        printf("Case #%d:\n",ca++);
        while(m--) {
            scanf("%s%d",c,&l);
            if(c[0]=='Q') {
                scanf("%d",&r);
                ll res=query(1,n,1,++l,++r);
                bool flag=1;
                if(mp.find(res)==mp.end())flag=0;
                printf("%s\n",flag?"Yes":"No");
                continue;
            }
            scanf("%s",c);
            update(1,n,1,++l,c[0]-'a'+1);
        }
    }
    return 0;
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章