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
分析:比赛时未做出,还是太菜。。
事实证明只要不是太暴力都能过吧,大概。。
按题解说,前缀和后缀分别按字典序排序,然后对询问二分到端点所在区间;
这样问题转化为了扫描线,可以用数据结构离线查询;
然后因为有重叠,所以枚举重叠长度哈希即可;
用了string,map,发现其实评测机还是很快的,orz;
代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <climits> #include <cstring> #include <string> #include <set> #include <bitset> #include <map> #include <queue> #include <stack> #include <vector> #include <cassert> #include <ctime> #define rep(i,m,n) for(i=m;i<=(int)n;i++) #define mod 998244353 #define inf 0x3f3f3f3f #define vi vector<int> #define pb push_back #define mp make_pair #define fi first #define se second #define ll long long #define pi acos(-1.0) #define pii pair<int,int> #define sys system("pause") #define ls rt<<1 #define rs rt<<1|1 #define all(x) x.begin(),x.end() const int maxn=1e5+10; const int N=5e5+10; using namespace std; ll gcd(ll p,ll q){return q==0?p:gcd(q,p%q);} ll qmul(ll p,ll q,ll mo){ll f=0;while(q){if(q&1)f=(f+p)%mo;p=(p+p)%mo;q>>=1;}return f;} ll qpow(ll p,ll q,ll mo){ll f=1;while(q){if(q&1)f=f*p%mo;p=p*p%mo;q>>=1;}return f;} int n,m,k,t,ret[maxn],dq[maxn],td1[maxn],td2[maxn],id1[maxn],id2[maxn]; map<unsigned ll,int>pq; unsigned ll h[2][maxn],xp[maxn]; string a[maxn],b[maxn],c,d; void init() { xp[0]=1; for(int i=1;i<=maxn-10;i++)xp[i]=xp[i-1]*123; } void ha(string p) { unsigned ll now=0; int len=p.length(); for(int i=len-1;i>=0;i--)now=now*123+p[i]; pq[now]=1; } void ha(string p,int tp,int len) { h[tp][len]=0; for(int i=len-1;i>=0;i--)h[tp][i]=h[tp][i+1]*123+p[i]; } bool cmp1(int x,int y){return a[x]<a[y];} bool cmp2(int x,int y){return b[x]<b[y];} void add(int x,int y) { while(x<=n)dq[x]+=y,x+=x&(-x); } int get(int x) { int ret=0; while(x)ret+=dq[x],x-=x&(-x); return ret; } vi qu[maxn],pos[maxn]; struct node { int x,y,z,w; }q[maxn]; int main() { int i,j; init(); scanf("%d",&t); while(t--) { pq.clear(); scanf("%d%d",&n,&m); rep(i,1,n) { cin>>a[i]; b[i]=a[i]; reverse(b[i].begin(),b[i].end()); ha(a[i]); id1[i]=id2[i]=i; dq[i]=0; } sort(id1+1,id1+n+1,cmp1); sort(id2+1,id2+n+1,cmp2); sort(a+1,a+n+1); sort(b+1,b+n+1); rep(i,1,n)td1[id1[i]]=i,td2[id2[i]]=i; rep(i,1,n)pos[td1[i]].pb(td2[i]); rep(i,1,m) { ret[i]=0; cin>>c>>d; int len1=c.length(),len2=d.length(); ha(c,0,len1); ha(d,1,len2); int l=len1-1,r=0; while(l>=0&&r<len2) { if(h[0][l]-h[0][len1]*xp[len1-l]==h[1][0]-h[1][r+1]*xp[r+1]) { unsigned ll tmp=h[0][0]-h[0][l]*xp[l]+h[1][0]*xp[l]; if(pq.count(tmp))ret[i]--; } --l,++r; } reverse(d.begin(),d.end()); int pos1=0,pos2=0,pos3=0,pos4=0; l=1,r=n; while(l<=r) { int mid=l+r>>1; if(a[mid]>=c)pos1=mid,r=mid-1; else l=mid+1; } if(pos1&&a[pos1].substr(0,len1)!=c)pos1=0; l=1,r=n; while(l<=r) { int mid=l+r>>1; if(a[mid]<=c||a[mid].substr(0,len1)==c)pos2=mid,l=mid+1; else r=mid-1; } l=1,r=n; while(l<=r) { int mid=l+r>>1; if(b[mid]>=d)pos3=mid,r=mid-1; else l=mid+1; } if(pos3&&b[pos3].substr(0,len2)!=d)pos3=0; l=1,r=n; while(l<=r) { int mid=l+r>>1; if(b[mid]<=d||b[mid].substr(0,len2)==d)pos4=mid,l=mid+1; else r=mid-1; } if(pos1&&pos3) { q[i]=node{pos1,pos3,pos2,pos4}; qu[pos1-1].pb(-i),qu[pos2].pb(i); } } rep(i,1,n) { rep(j,0,pos[i].size()-1)add(pos[i][j],1); rep(j,0,qu[i].size()-1) { int x=qu[i][j]; if(x<0) { x=-x; ret[x]-=get(q[x].w)-get(q[x].y-1); } else ret[x]+=get(q[x].w)-get(q[x].y-1); } } rep(i,1,m)printf("%d ",ret[i]); rep(i,1,n)qu[i].clear(),pos[i].clear(); } return 0; }