HDU 6096 String 排序 + 线段树 + 扫描线
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
题意:
给你n个母串,m个询问
每次询问给你一个前缀,后缀
问你有多少个母串的前缀,后缀等于当前,且不相交
题解:
先将所有母串正串,反串排序,那么每个询问的前缀后缀,会对应存在于两段区间
现在要查询的就是这两个区间同时存在哪些母串数量
将母串在正串,反串存在的位置x,y看作一个点,查询的看作一个区间,这个就是平面上一个矩阵包含多少个点,用线段树+扫描线解决
有一种情况是重复的了比如 母串含有 aaa,查询aa aa
这个时候就遍历重叠的是哪一部分,hash去重就行了
#include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define ls i<<1 #define rs ls | 1 #define mid ((ll+rr)>>1) #define pii pair<int,int> #define MP make_pair typedef long long LL; typedef unsigned long long ULL; const long long INF = 1e18+1LL; const double pi = acos(-1.0); const int N = 5e5+10, M = 1e3+20,inf = 2e9; const ULL mod = 1004535809ULL; int n,m,ans[N],t; struct ss{ string s; int id; }a[N],b[N]; string c[N],d[N]; struct Point{ int x,y,id; bool operator < (const Point &j) const { if(x == j.x) return y < j.y; else return x < j.x; } }p[N]; bool cmp(ss s1,ss s2) { return s1.s < s2.s; } struct Que{ int top,down,x,type,qid; bool operator < (const Que &j) const { if( x == j.x) return type > j.type; else return x < j.x; } }Q[N]; int sum[N * 4]; void build(int i,int ll,int rr) { sum[i] = 0; if(ll == rr) return ; build(ls,ll,mid);build(rs,mid+1,rr); } void update(int i,int ll,int rr,int x) { if(ll == rr) { sum[i] += 1; return ; } if(x <= mid) update(ls,ll,mid,x); else update(rs,mid+1,rr,x); sum[i] = sum[ls] + sum[rs]; } int ask(int i,int ll,int rr,int x,int y) { if(ll == x && rr == y) return sum[i]; if(y <= mid) return ask(ls,ll,mid,x,y); else if(x > mid) return ask(rs,mid+1,rr,x,y); else return ask(ls,ll,mid,x,mid) + ask(rs,mid+1,rr,mid+1,y); } map<string ,int > mp; ULL sqr[N]; void init() { mp.clear(); for(int i = 1; i <= m; ++i) ans[i] = 0; } int main() { int T; sqr[0] = 1LL; for(int i = 1; i < N; ++i) sqr[i] = sqr[i-1] * mod; scanf("%d",&T); while(T--) { scanf("%d%d",&n,&m); init(); for(int i = 1; i <= n; ++i) { cin>>a[i].s;a[i].id = i; b[i] = a[i]; reverse(b[i].s.begin(),b[i].s.end()); c[i] = a[i].s; d[i] = b[i].s; mp[c[i]] += 1; } sort(a+1,a+n+1,cmp); sort(b+1,b+n+1,cmp); for(int i = 1; i <= n; ++i) p[a[i].id].x = i,p[b[i].id].y = i; sort(d+1,d+n+1); sort(c+1,c+n+1); int cnt = 0; for(int i = 1; i <= m; ++i) { cin>>c[0]>>d[0]; reverse(d[0].begin(),d[0].end()); int l = lower_bound(c+1,c+n+1,c[0]) - c; c[0] += ('z'+1); int r = lower_bound(c+1,c+n+1,c[0]) - c - 1; c[0].erase(--c[0].end()); int l1 = lower_bound(d+1,d+n+1,d[0]) - d; d[0] += ('z'+1); int r1 = lower_bound(d+1,d+n+1,d[0]) - d - 1; d[0].erase(--d[0].end()); reverse(d[0].begin(),d[0].end()); if(l > r || l1 > r1) ans[i] = 0; else { ++cnt; Q[cnt].top = r1; Q[cnt].x = l-1; Q[cnt].down = l1; Q[cnt].type = -1; Q[cnt].qid = i; ++cnt; Q[cnt].top = r1; Q[cnt].x = r; Q[cnt].down = l1; Q[cnt].type = 0; Q[cnt].qid = i; } for(int j = c[0].length() - 1,k = 0; k < d[0].length() && c[0].begin()!=c[0].end(); j = c[0].length() - 1,++k) { // cout<<c[0][j]<<" "<<d[0][k]<<endl; if(c[0][j] == d[0][k]) { c[0].erase((--c[0].end())); ans[i] -= mp[c[0] + d[0]]; }else break; } } for(int i = 1; i <= n; ++i) { ++cnt; Q[cnt].top = p[i].y; Q[cnt].x = p[i].x; Q[cnt].type = 1; } build(1,1,n); sort(Q+1,Q+cnt+1); for(int i = 1; i <= cnt; ++i) { if(Q[i].type == 1) { update(1,1,n,Q[i].top); } if(Q[i].type == 0) { ans[Q[i].qid] += ask(1,1,n,Q[i].down,Q[i].top); } if(Q[i].type == -1) { ans[Q[i].qid] -= ask(1,1,n,Q[i].down,Q[i].top); } } for(int i = 1; i <= m; ++i) { printf("%d\n",ans[i]); } } return 0; } /* 1 1 1 aaa aa aa */