HDU - 3973 AC's String(Hash+线段树)

Posted fht-litost

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU - 3973 AC's String(Hash+线段树)相关的知识,希望对你有一定的参考价值。

http://acm.hdu.edu.cn/showproblem.php?pid=3973

题意

给一个词典和一个主串。有两种操作,查询主串某个区间,问这主串区间中包含多少词典中的词语。修改主串某一位置的字符。

 

分析

题目要求区间查询,和单点更新,那么最先想到的应该是线段树。可字符串怎么利用线段树呢?用hash!首先将词典按规则hash后放入map,然后将主串的hash值放置入线段树中。问题来了,怎么更新结点的hash值呢?假如现在我们知道了s[l...mid]和s[mid+1...r]的hash值,我需要s[l...r]的hash值,根据我的hash规则(将主串看作是p进制数,左边为高位,p为素数),hash[l...r]=hash[l...mid]*p^(r-mid)+hash[mid+1...r]。另外,被输入卡了好久。。不停RE。需要使用更准确的输入格式,我猜测可能是输入数据之间的空格不定导致的。

#include<iostream>
#include<cmath>
#include<cstring>
#include<queue>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<map>
#include<set>
#define rep(i,e) for(int i=0;i<(e);i++)
#define rep1(i,e) for(int i=1;i<=(e);i++)
#define repx(i,x,e) for(int i=(x);i<=(e);i++)
#define X first
#define Y second
#define PB push_back
#define MP make_pair
#define mset(var,val) memset(var,val,sizeof(var))
#define scd(a) scanf("%d",&a)
#define scdd(a,b) scanf("%d%d",&a,&b)
#define scddd(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define pd(a) printf("%d
",a)
#define scl(a) scanf("%lld",&a)
#define scll(a,b) scanf("%lld%lld",&a,&b)
#define sclll(a,b,c) scanf("%lld%lld%lld",&a,&b,&c)
#define IOS ios::sync_with_stdio(false);cin.tie(0)
#define lc idx<<1
#define rc idx<<1|1
#define lson l,mid,lc
#define rson mid+1,r,rc
using namespace std;
typedef long long ll;
template <class T>
void test(T a){cout<<a<<endl;}
template <class T,class T2>
void test(T a,T2 b){cout<<a<<" "<<b<<endl;}
template <class T,class T2,class T3>
void test(T a,T2 b,T3 c){cout<<a<<" "<<b<<" "<<c<<endl;}
const int N = 1e6+10;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3fll;
const ll mod = 1000000007;
int T;
void testcase(){
    printf("Case #%d:
",++T);
}
const int MAXN = 1e5+10;
const int MAXM = 30;
const int p = 19;

struct node{
    int l,r;
    ll hass;
}tree[MAXN<<2];
char str[2000010];
ll P[MAXN];
map<ll,int> ma;
int n;
void init(){
    P[0]=1;
    for(int i=1;i<MAXN;i++){
        P[i]=p*P[i-1];
    }
}
void Hash(char s[]){
    int len = strlen(s);
    ll res=0;
    for(int i=0;i<len;i++){
        res +=P[len-1-i]*(s[i]-a+1);
    }
    ma[res]=1;
}
void push_up(int m,int idx){
    tree[idx].hass=tree[lc].hass*P[m]+tree[rc].hass;
}
void build(int l,int r,int idx){
    tree[idx].l=l,tree[idx].r=r;
    if(l==r){
        tree[idx].hass=str[l]-a+1;
        return;
    }
    int mid = (l+r)>>1;
    build(lson);
    build(rson);
    push_up(r-mid,idx);
}
void update(int pos,int idx){
    if(tree[idx].l==tree[idx].r){
        tree[idx].hass=str[pos]-a+1;
        return;
    }
    int mid = (tree[idx].l+tree[idx].r)>>1;
    if(pos<=mid) update(pos,lc);
    else update(pos,rc);
    push_up(tree[idx].r-mid,idx);
}
ll query(int l,int r,int idx){
    if(tree[idx].l>=l&&tree[idx].r<=r)
        return tree[idx].hass;
    int mid = (tree[idx].l+tree[idx].r)>>1;
    if(r<=mid) return query(l,r,lc);
    else if(l>mid) return query(l,r,rc);
    return query(l,mid,lc)*P[r-mid]+query(mid+1,r,rc);
}

int main() {
#ifdef LOCAL
    freopen("in.txt","r",stdin);
#endif // LOCAL
    int t,m;
    scd(t);
    init();
    T=0;
    char s1[10],s2[10];
    while(t--){
        testcase();
        ma.clear();
        scd(n);
        for(int i=0;i<n;i++){
            scanf("%s",str);
            Hash(str);
        }
        scanf("%s",str);
        int len = strlen(str);
        build(0,len-1,1);
        scd(m);
        while(m--){
            scanf("%s",s1);
            if(s1[0]==Q){
                int l,r;
                scdd(l,r);
                if(ma.find(query(l,r,1))!=ma.end()) puts("Yes");
                else puts("No");
            }else{
                int pos;
                scanf("%d%s",&pos,s2);
                str[pos]=s2[0];
                update(pos,1);
            }
        }
    }
    return 0;
}

 

以上是关于HDU - 3973 AC's String(Hash+线段树)的主要内容,如果未能解决你的问题,请参考以下文章

AC日记——Aragorn's Story HDU 3966

HDU 2200 Eddy's AC难题

HDU 3341 Lost's revenge(AC自动机+状压DP)

HDU - 3341 Lost&#39;s revenge(AC自己主动机+DP)

HDU3341 Lost's revenge(AC自动机+DP)

L - Lost's revenge HDU - 3341 (AC自动机 + 记忆化搜索 + 变进制算法)