zoukankan      html  css  js  c++  java
  • HDU 6096 String 排序 + 线段树 + 扫描线

    String

    Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)


    Problem Description
    Bob has a dictionary with N words in it.
    Now there is a list of words in which the middle part of the word has continuous letters disappeared. The middle part does not include the first and last character.
    We only know the prefix and suffix of each word, and the number of characters missing is uncertain, it could be 0. But the prefix and suffix of each word can not overlap.
    For each word in the list, Bob wants to determine which word is in the dictionary by prefix and suffix.
    There are probably many answers. You just have to figure out how many words may be the answer.

    Input
    The first line of the input gives the number of test cases T; T test cases follow.
    Each test case contains two integer N and Q, The number of words in the dictionary, and the number of words in the list.
    Next N line, each line has a string Wi, represents the ith word in the dictionary (0<|Wi|≤100000)
    Next Q line, each line has two string Pi , Si, represents the prefix and suffix of the ith word in the list (0<|Pi|,|Si|≤100000,0<|Pi|+|Si|≤100000)
    All of the above characters are lowercase letters.
    The dictionary does not contain the same words.

    Limits
    T≤5
    0<N,Q≤100000
    ∑Si+Pi≤500000
    ∑Wi≤500000

    Output
    For each test case, output Q lines, an integer per line, represents the answer to each word in the list.

    Sample Input
    1
    4 4
    aba
    cde
    acdefa
    cdef
    a a
    cd ef
    ac a
    ce f

    Sample Output
    2
    1
    1
    0

    题意:

      给你n个母串,m个询问

      每次询问给你一个前缀,后缀

      问你有多少个母串的前缀,后缀等于当前,且不相交

    题解:

      先将所有母串正串,反串排序,那么每个询问的前缀后缀,会对应存在于两段区间

      现在要查询的就是这两个区间同时存在哪些母串数量

      将母串在正串,反串存在的位置x,y看作一个点,查询的看作一个区间,这个就是平面上一个矩阵包含多少个点,用线段树+扫描线解决

      有一种情况是重复的了比如 母串含有 aaa,查询aa aa

      这个时候就遍历重叠的是哪一部分,hash去重就行了

    #include<bits/stdc++.h>
    using namespace std;
    #pragma comment(linker, "/STACK:102400000,102400000")
    #define ls i<<1
    #define rs ls | 1
    #define mid ((ll+rr)>>1)
    #define pii pair<int,int>
    #define MP make_pair
    typedef long long LL;
    typedef unsigned long long ULL;
    const long long INF = 1e18+1LL;
    const double pi = acos(-1.0);
    const int N = 5e5+10, M = 1e3+20,inf = 2e9;
    
    const ULL mod = 1004535809ULL;
    int n,m,ans[N],t;
    struct ss{
        string s;
        int id;
    }a[N],b[N];
    string c[N],d[N];
    struct Point{
        int x,y,id;
        bool operator < (const Point &j) const {
            if(x == j.x) return y < j.y;
            else return x < j.x;
        }
    }p[N];
    
    bool cmp(ss s1,ss s2) {
        return s1.s < s2.s;
    }
    struct Que{
        int top,down,x,type,qid;
        bool operator < (const Que &j) const {
            if( x == j.x)
                return type > j.type;
            else return x < j.x;
        }
    }Q[N];
    
    
    int sum[N * 4];
    void build(int i,int ll,int rr) {
        sum[i] = 0;
        if(ll == rr) return ;
        build(ls,ll,mid);build(rs,mid+1,rr);
    }
    void update(int i,int ll,int rr,int x) {
        if(ll == rr) {
            sum[i] += 1;
            return ;
        }
        if(x <= mid) update(ls,ll,mid,x);
        else update(rs,mid+1,rr,x);
        sum[i] = sum[ls] + sum[rs];
    }
    int ask(int i,int ll,int rr,int x,int y) {
        if(ll == x && rr == y) return sum[i];
        if(y <= mid) return ask(ls,ll,mid,x,y);
        else if(x > mid) return ask(rs,mid+1,rr,x,y);
        else return ask(ls,ll,mid,x,mid) + ask(rs,mid+1,rr,mid+1,y);
    }
    map<string ,int > mp;
    ULL sqr[N];
    
    void init() {
        mp.clear();
        for(int i = 1; i <= m; ++i) ans[i] = 0;
    }
    int main() {
        int T;
        sqr[0] = 1LL;
        for(int i = 1; i < N; ++i) sqr[i] = sqr[i-1] * mod;
        scanf("%d",&T);
        while(T--) {
            scanf("%d%d",&n,&m);
            init();
            for(int i = 1; i <= n; ++i) {
                cin>>a[i].s;a[i].id = i;
                b[i] = a[i];
                reverse(b[i].s.begin(),b[i].s.end());
                c[i] = a[i].s;
                d[i] = b[i].s;
    
                mp[c[i]] += 1;
            }
            sort(a+1,a+n+1,cmp);
            sort(b+1,b+n+1,cmp);
    
            for(int i = 1; i <= n; ++i)
                p[a[i].id].x = i,p[b[i].id].y = i;
    
    
            sort(d+1,d+n+1);
            sort(c+1,c+n+1);
            int cnt = 0;
            for(int i = 1; i <= m; ++i) {
                cin>>c[0]>>d[0];
                reverse(d[0].begin(),d[0].end());
                int l = lower_bound(c+1,c+n+1,c[0]) - c;
                c[0] += ('z'+1);
                int r = lower_bound(c+1,c+n+1,c[0]) - c - 1;
               c[0].erase(--c[0].end());
                int l1 = lower_bound(d+1,d+n+1,d[0]) - d;
    
                d[0] += ('z'+1);
                int r1 = lower_bound(d+1,d+n+1,d[0]) - d - 1;
                d[0].erase(--d[0].end());
                reverse(d[0].begin(),d[0].end());
                if(l > r || l1 > r1) ans[i] = 0;
                else {
                    ++cnt;
                    Q[cnt].top = r1;
                    Q[cnt].x = l-1;
                    Q[cnt].down = l1;
                    Q[cnt].type = -1;
                    Q[cnt].qid = i;
    
                    ++cnt;
                    Q[cnt].top = r1;
                    Q[cnt].x = r;
                    Q[cnt].down = l1;
                    Q[cnt].type = 0;
                    Q[cnt].qid = i;
                }
    
                for(int j = c[0].length() - 1,k = 0; k < d[0].length() && c[0].begin()!=c[0].end(); j = c[0].length() - 1,++k)
                 {
                    // cout<<c[0][j]<<" "<<d[0][k]<<endl;
                     if(c[0][j] == d[0][k])
                   {
                       c[0].erase((--c[0].end()));
                       ans[i] -= mp[c[0] + d[0]];
                   }else break;
                 }
    
            }
            for(int i = 1; i <= n; ++i) {
                ++cnt;
                Q[cnt].top = p[i].y;
                Q[cnt].x = p[i].x;
                Q[cnt].type = 1;
            }
            build(1,1,n);
            sort(Q+1,Q+cnt+1);
            for(int i = 1; i <= cnt; ++i) {
                if(Q[i].type == 1) {
                    update(1,1,n,Q[i].top);
                }
                if(Q[i].type == 0) {
                    ans[Q[i].qid] += ask(1,1,n,Q[i].down,Q[i].top);
                }
                if(Q[i].type == -1) {
                    ans[Q[i].qid] -= ask(1,1,n,Q[i].down,Q[i].top);
                }
            }
            for(int i = 1; i <= m; ++i) {
                printf("%d
    ",ans[i]);
            }
        }
        return 0;
    }
    
    
    /*
    1
    1 1
    aaa
    aa aa
    */
  • 相关阅读:
    mysql高效分页
    mybatis插入值为空时需要制定类型
    NoClassDefFoundError
    mybatis动态sql中的两个内置参数(_parameter和_databaseId)
    Java位运算在程序设计中的使用:位掩码(BitMask)
    基于netty的聊天室(保持和获取客户端channel)
    Netty自定义协议半包编解码
    位运算基础
    JAVA加密系列(四)- 位运算加密(异或加密)
    位运算基础
  • 原文地址:https://www.cnblogs.com/zxhl/p/7346475.html
Copyright © 2011-2022 走看看