zoukankan      html  css  js  c++  java
  • dtoj2099. 字符串查询( find)

    给定n个字符串和q个询问

    每次询问在这n个字符串中,有多少个字符串同时满足

    1. 字符串a是它的前缀

    2. 字符串b是它的后缀

    内存128M


    Sol

    这题我想了个log的做法可是它卡空间!!

    可以建两个AC自动机,然后相当于给你一个点的映射,每次询问两颗子树内相同的点有几个。

    那么在一个树上线段树合并,另一个区间查询就是nlog的

    那么这一题我们只好先把字符串排序,然后二分出a的可行区间,b的可行区间。

    离线完a树状数组维护就行。

    效率nlog2

    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<vector>
    #define ll unsigned long long
    #define p 793999
    #define maxn 50005
    using namespace std;
    int n,Q;
    int tr[maxn],dy[maxn],ans[maxn];
    void add(int i,int v){
        for(;i<=n;i+=i&-i)tr[i]+=v;
    }
    int ask(int i){
        int sum=0;for(;i;i-=i&-i)sum+=tr[i];return sum;
    }
    struct node{
        int id,len;
        char ch[105];
        ll h[105];
        void R(){
            scanf("%s",ch+1);len=strlen(ch+1);
            for(int j=1;j<=len;j++)h[j]=h[j-1]*p+ch[j];
        }
        void re(){
            for(int i=1,j=len;i<j;i++,j--)swap(ch[i],ch[j]);
            for(int j=1;j<=len;j++)h[j]=h[j-1]*p+ch[j];
        }
    }s[maxn],S[maxn],a,b;
    struct que{
        int id,op,l,r;
    };
    vector<que>q[maxn];
    bool operator ==(node A,node B){
        if(A.len!=B.len)return 0;
        return A.h[A.len]==B.h[B.len];
    }
    int find(node A,node B){
        int M=min(A.len,B.len);
        if(A.ch[1]!=B.ch[1])return 0;
        int l=1,r=M;
        while(l<r){
            int mid=(l+r+1)>>1;
            if(A.h[mid]==B.h[mid])l=mid;
            else r=mid-1;
        }
        return l;
    }
    bool operator <(node A,node B){
        int x=find(A,B);
        if(min(A.len,B.len)==x)return A.len<B.len;
        return A.ch[x+1]<B.ch[x+1];
    }
    bool cmp(node a,node b){
        return a<b;
    }
    int get(int l,node t){
        int r=n;
        while(l<r){
            int mid=l+r+1>>1;
            if(find(s[mid],t)==t.len)l=mid;
            else r=mid-1;
        }
        return l;
    }
    int Get(int l,node t){
        int r=n;
        while(l<r){
            int mid=l+r+1>>1;
            if(find(S[mid],t)==t.len)l=mid;
            else r=mid-1;
        }
        return l;
    }
    int main(){
        cin>>n>>Q;
        for(int i=1;i<=n;i++)s[i].R();
        sort(s+1,s+n+1,cmp);
        for(int i=1;i<=n;i++){
            s[i].id=i;
            S[i]=s[i];S[i].re();
        }
        sort(S+1,S+n+1,cmp);
        for(int i=1;i<=n;i++)dy[S[i].id]=i;
        for(int i=1;i<=Q;i++){
            a.R();b.R();b.re();
            int l=lower_bound(s+1,s+n+1,a)-s,r=get(l,a);
            int L=lower_bound(S+1,S+n+1,b)-S,R=Get(L,b);
            if(l>n||L>n)continue;
            if(find(s[l],a)!=a.len)continue;
            if(find(S[L],b)!=b.len)continue;
            q[l-1].push_back((que){i,-1,L,R});
            q[r].push_back((que){i,1,L,R});
        }
        for(int i=1;i<=n;i++){
            add(dy[i],1);
            for(int j=0;j<q[i].size();j++){
                que t=q[i][j];
                ans[t.id]+=t.op*(ask(t.r)-ask(t.l-1));
            }
        }
        for(int i=1;i<=Q;i++)printf("%d
    ",ans[i]);
        return 0;
    }
    View Code

     

  • 相关阅读:
    asd
    自勉
    php cli 参数
    编译
    WebMisSharp的协同开发
    WebMisDeveloper4.5.0 基于Ext.net,Extjs,MVC/简单三层的自动生成开发利器
    WebMisDeveloper更新专版
    外设驱动库开发笔记37:S13365BQ光敏二极管作为光度计驱动
    Java学习笔记之多线程 生产者 消费者
    Java学习笔记之IO流&Properties集合
  • 原文地址:https://www.cnblogs.com/liankewei/p/12253458.html
Copyright © 2011-2022 走看看