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\n",ans[i]);
    return 0;
}
View Code

 

 

 

posted @ 2020-02-02 20:07  liankewei123456  阅读(161)  评论(0编辑  收藏  举报