• 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
    */
  • 相关阅读:
    css3 过渡
    2021.1.5 算法实训
    表单 form
    表格 table
    Windows系统重装记录
    多线程【基础】
    关于excuteQuery与execute()
    关于jsp的action如何调用servlet的自定义方法
    selenium
    验证码处理
  • 原文地址:https://www.cnblogs.com/zxhl/p/7346475.html
Copyright © 2020-2023  润新知