HDU 6096 String 排序 + 线段树 + 扫描线
2017-08-11 16:11
183 查看
[b]String[/b]
[b]Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)[/b]
[b]Problem Description[/b]
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.
[b]Input[/b]
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
[b]Output[/b]
For each test case, output Q lines, an integer per line, represents the answer to each word in the list.
[b]Sample Input[/b]
1
4 4
aba
cde
acdefa
cdef
a a
cd ef
ac a
ce f
[b]Sample Output[/b]
2
1
1
0
[b]题意:[/b]
给你n个母串,m个询问
每次询问给你一个前缀,后缀
问你有多少个母串的前缀,后缀等于当前,且不相交
题解:
先将所有母串正串,反串排序,那么每个询问的前缀后缀,会对应存在于两段区间
现在要查询的就是这两个区间同时存在哪些母串数量
将母串在正串,反串存在的位置x,y看作一个点,查询的看作一个区间,这个就是平面上一个矩阵包含多少个点,用线段树+扫描线解决
有一种情况是重复的了比如 母串含有 aaa,查询aa aa
这个时候就遍历重叠的是哪一部分,hash去重就行了
[b]Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 524288/524288 K (Java/Others)[/b]
[b]Problem Description[/b]
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.
[b]Input[/b]
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
[b]Output[/b]
For each test case, output Q lines, an integer per line, represents the answer to each word in the list.
[b]Sample Input[/b]
1
4 4
aba
cde
acdefa
cdef
a a
cd ef
ac a
ce f
[b]Sample Output[/b]
2
1
1
0
[b]题意:[/b]
给你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 ,t; struct ss{ string s; int id; }a ,b ; string c ,d ; 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 ; 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 ; 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 ; 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 */
相关文章推荐
- HDU 1255(线段树,扫描线,矩形的面积交)
- hdu 1542 & poj 1151 Atlantis 线段树扫描线求矩形面积并
- HDU - 1542 Atlantis(线段树 扫描线)
- hdu 5091 (线段树,扫描线)
- hdu 1542 扫描线+线段树求矩阵面积并
- HDU 1542 Atlantis (线段树 + 扫描线 + 离散化)
- HDU 1542 Atlantis(离散化+扫描线(求并面积)+线段树)
- HDU_1542 Atlantis[线段树扫描线]
- HDU 1542 Atlantis [离散化 + 扫描线 + 线段树]
- HDU 1542 Atlantis 线段树 (扫描线 + 离散化)
- HDU 1542 Atlantis(线段树+扫描线求面积并)
- hdu 1255 覆盖的面积 (线段树扫描线 计算两次覆盖的面积)
- HDU-1255 覆盖的面积(线段树扫描线模板+离散化+加点修改题)
- hdu 1255 覆盖的面积 线段树扫描线求重叠面积
- HDU-1255 覆盖的面积 线段树 + 扫描线
- HDU 1542 Atlantis [离散化 + 扫描线 + 线段树]
- HDU1542 Atlantis(扫描线+矩形面积并+线段树)
- poj 1151 hdu 1542 Atlantis 线段树扫描线,详细讲解,(*^__^*) 嘻嘻……
- hdu 1542 Atlantis(线段树,扫描线)
- hdu 1542 Atlantis(线段树,扫描线之面积并)