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
    */
  • 相关阅读:
    分布式跑批的实现流程
    Java1.8新特性Stream流处理集合元素
    RocketMQ消息存储和查询原理(引用清幽之地 清幽之地的博客)
    Markdown使用持续更新
    一次百万请求mq堆积的生产排查
    Spring Boot打包部署修改jar文件名
    Spring Boot的应用启动器
    Spring Boot配置文件application.properties
    Eclipse中出现.classPath(拒绝访问)
    PHP文件上传的相关配置
  • 原文地址:https://www.cnblogs.com/zxhl/p/7346475.html
Copyright © 2011-2022 走看看