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; }