标签:begin code 字符串 字符 一段 nbsp insert memset 树套树
思路:
网上的题解有AC自动机的,有trie树的,还有(乱搞?)的
首先把输入的那n个串按照字典序排序,
把n个串翻转以后再按照字典序排序
这样我们发现, 查的前缀在字典序排序后是一段区间,
查的后缀翻转一下在翻转后的字典序排序以后也是一段区间
这样如果不考虑重叠的问题,就是一个简单的二维数点问题,一维排序,一维线段树即可解决
如果有重叠的问题,我们需要搞出来每个字符串的长度,使给出的前缀长+后缀长>=原字符串长度
此时题目变成了三维偏序,排序后树套树即可。
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=500050; int cases,n,q,root[N<<3],cnt,tree[N*150],lson[N*150],rson[N*150]; struct Node{string str;int id,len;}X[N],Y[N],tmp; bool operator<(Node a,Node b){return a.str<b.str;} struct Pnt{int x,y,z;}p[N]; struct Ask{int xl,xr,yl,yr,z,id,ans;}ask[N]; bool cmp1(Pnt a,Pnt b){return a.z>b.z;} bool cmp2(Ask a,Ask b){return a.z>b.z;} bool cmp3(Ask a,Ask b){return a.id<b.id;} void Insert(int l,int r,int &pos,int wei){ if(!pos)pos=++cnt;tree[pos]++; if(l==r)return; int mid=(l+r)>>1; if(mid>=wei)Insert(l,mid,lson[pos],wei); else Insert(mid+1,r,rson[pos],wei); } void insert(int l,int r,int pos,int num,int wei){ Insert(1,n,root[pos],wei); if(l==r)return; int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1; if(mid<num)insert(mid+1,r,rson,num,wei); else insert(l,mid,lson,num,wei); } int Query(int l,int r,int pos,int L,int R){ if(l>=L&&r<=R)return tree[pos]; int mid=(l+r)>>1; if(mid<L)return Query(mid+1,r,rson[pos],L,R); else if(mid>=R)return Query(l,mid,lson[pos],L,R); else return Query(l,mid,lson[pos],L,R)+Query(mid+1,r,rson[pos],L,R); } int query(int l,int r,int pos,int xl,int xr,int yl,int yr){ if(l>=xl&&r<=xr)return Query(1,n,root[pos],yl,yr); int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1; if(mid<xl)return query(mid+1,r,rson,xl,xr,yl,yr); else if(mid>=xr)return query(l,mid,lson,xl,xr,yl,yr); else return query(l,mid,lson,xl,xr,yl,yr)+query(mid+1,r,rson,xl,xr,yl,yr); } int main(){ ios::sync_with_stdio(false); cin>>cases; while(cases--){ memset(tree,0,sizeof(int)*(cnt+5)); memset(lson,0,sizeof(int)*(cnt+5)); memset(rson,0,sizeof(int)*(cnt+5)); memset(root,0,sizeof(root));cnt=0; cin>>n>>q; for(int i=1;i<=n;i++)cin>>X[i].str; sort(X+1,X+1+n); for(int i=1;i<=n;i++)X[i].id=i,X[i].len=X[i].str.length(); for(int i=1;i<=n;i++)Y[i]=X[i]; for(int i=1;i<=n;i++)reverse(Y[i].str.begin(),Y[i].str.end()); sort(Y+1,Y+1+n); for(int i=1;i<=n;i++)p[i].x=Y[i].id,p[i].y=i,p[i].z=Y[i].len; for(int i=1;i<=q;i++){ string pre,suf;cin>>pre>>suf; ask[i].id=i;tmp.str=pre; ask[i].xl=lower_bound(X+1,X+1+n,tmp)-X; tmp.str=pre,tmp.str.push_back(‘z‘+1); ask[i].xr=lower_bound(X+1,X+1+n,tmp)-X-1; tmp.str=suf,reverse(tmp.str.begin(),tmp.str.end()); ask[i].yl=lower_bound(Y+1,Y+1+n,tmp)-Y; tmp.str.push_back(‘z‘+1); ask[i].yr=lower_bound(Y+1,Y+1+n,tmp)-Y-1; ask[i].z=pre.size()+suf.size(); } sort(p+1,p+1+n,cmp1);sort(ask+1,ask+1+q,cmp2); int tt=1; for(int i=1;i<=q;i++){ while(p[tt].z>=ask[i].z&&tt<=n)insert(1,n,1,p[tt].x,p[tt].y),tt++; if(ask[i].xl>ask[i].xr||ask[i].yl>ask[i].yr){ask[i].ans=0;continue;} ask[i].ans=query(1,n,1,ask[i].xl,ask[i].xr,ask[i].yl,ask[i].yr); }sort(ask+1,ask+1+q,cmp3); for(int i=1;i<=q;i++)cout<<ask[i].ans<<endl; } }
标签:begin code 字符串 字符 一段 nbsp insert memset 树套树
原文地址:https://www.cnblogs.com/SiriusRen/p/9424836.html