zoukankan      html  css  js  c++  java
  • HDU

    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;
    }
  • 相关阅读:
    window打开服务的dos命令
    struts(三) ---OGNL的学习和理解
    struts(二) ---中参数传值
    struts入门初步(一)
    javaSE之Object及hashcode等相关知识
    CSS小三角制作
    VM安装mac及dmg文件转换iso
    单例模式的学习与简单应用
    Tortoise 下修改服务器路径(Relocate与Switch)
    连接未关闭。 连接的当前状态为打开。问题的解决
  • 原文地址:https://www.cnblogs.com/fht-litost/p/9287198.html
Copyright © 2011-2022 走看看