BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster( 后缀数组 + 二分 + RMQ + 树状数组 )
生活随笔
收集整理的這篇文章主要介紹了
BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster( 后缀数组 + 二分 + RMQ + 树状数组 )
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
全部串起來做SA, 在按字典序排序的后綴中, 包含每個詢問串必定是1段連續的區間, 對每個詢問串s二分+RMQ求出包含s的區間. 然后就是求區間的不同的數的個數(經典問題), sort queries + BIT 就行了.時間復雜度O(N log N). 速度墊底了QAQ 你們都會SAM。。。。
----------------------------------------------------------------------
#include<cmath>#include<cstdio>#include<cctype>#include<cstring>#include<algorithm>using namespace std;?#define b(i) (1 << (i))
const int maxL = 540009;const int maxQ = 60009;char S[maxL], str[maxL];int N, n, q, Id[maxL], qL[maxQ], qR[maxQ], L[maxQ], R[maxQ];int Rank[maxL], Height[maxL], Sa[maxL], cnt[maxL];int RMQ[20][maxL], r[maxQ], ans[maxQ];void Build() {int m = 'z' + 1, *x = Rank, *y = Height;for(int i = 0; i < m; i++) cnt[i] = 0;for(int i = 0; i < N; i++) cnt[x[i] = S[i]]++;for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1];for(int i = N; i--; ) Sa[--cnt[x[i]]] = i;for(int k = 1, p = 0; k <= N; k <<= 1, p = 0) {for(int i = N - k; i < N; i++) y[p++] = i;for(int i = 0; i < N; i++)if(Sa[i] >= k) y[p++] = Sa[i] - k;for(int i = 0; i < m; i++) cnt[i] = 0;for(int i = 0; i < N; i++) cnt[x[y[i]]]++;for(int i = 1; i < m; i++) cnt[i] += cnt[i - 1];for(int i = N; i--; ) Sa[--cnt[x[y[i]]]] = y[i];swap(x, y);x[Sa[0]] = 0;p = 1;for(int i = 1; i < N; i++) {if(y[Sa[i]] != y[Sa[i - 1]] || y[Sa[i] + k] != y[Sa[i - 1] + k]) p++;x[Sa[i]] = p - 1;}if((m = p) >= N) break;}for(int i = 0; i < N; i++) Rank[Sa[i]] = i;Height[0] = Height[N] = 0;for(int i = 0, h = 0; i < N; i++) if(Rank[i]) {if(h) h--;while(S[i + h] == S[Sa[Rank[i] - 1] + h]) h++;Height[Rank[i]] = h;}}void Init_RMQ() {for(int i = 0; i < N; i++)RMQ[0][i] = Height[i];for(int i = 1; b(i) <= N; i++)for(int j = 0; j + b(i) <= N; j++)RMQ[i][j] = min(RMQ[i - 1][j], RMQ[i - 1][j + b(i - 1)]);}inline int LCP(int l, int r) {int t = log2(r - l + 1);return min(RMQ[t][l], RMQ[t][r - b(t) + 1]);}void calc(int &L, int &R, int p, int len) {int _l, _r;p = Rank[p];if(Height[p] >= len) {_l = 0, _r = p - 1;while(_l <= _r) {int m = (_l + _r) >> 1;if(LCP(m + 1, p) >= len)L = m, _r = m - 1;else_l = m + 1;}} elseL = p;if(Height[p + 1] >= len) {_l = p + 1, _r = N - 1;while(_l <= _r) {int m = (_l + _r) >> 1;if(LCP(p + 1, m) >= len)R = m, _l = m + 1;else_r = m - 1;}} elseR = p;}struct Link {int p;Link* n;} pool[maxL], *pt = pool, *H[maxL];inline void AddL(int v, int p) {pt->p = p, pt->n = H[v], H[v] = pt++;}int B[maxL];inline void Modify(int p, int v) {if(!p) return;for(; p <= N; p += p & -p) B[p] += v;}inline int Sum(int p) {int ret = 0;for(; p; p -= p & -p) ret += B[p];return ret;}inline bool Cmp(const int &l, const int &r) {return qL[l] < qL[r];}void Work() {Build();Init_RMQ();memset(B, 0, sizeof B);for(int i = N; i--; )if(Id[Sa[i]] >= 0) AddL(Id[Sa[i]], i);for(int i = 0; i < n; i++)Modify(H[i]->p + 1, 1);for(int i = 0; i < q; i++)calc(qL[r[i] = i], qR[i], L[i], R[i] - L[i]);sort(r, r + q, Cmp);int c = 0;for(int i = 0; i < N; i++) {while(qL[r[c]] == i) {ans[r[c]] = Sum(qR[r[c]] + 1) - Sum(qL[r[c]]);if(++c >= q) break;}if(c >= q) break;Modify(i + 1, -1);if(H[Id[Sa[i]]]) {H[Id[Sa[i]]] = H[Id[Sa[i]]]->n;if(H[Id[Sa[i]]])Modify(H[Id[Sa[i]]]->p + 1, 1);}}for(int i = 0; i < q; i++)printf("%d\n", ans[i]);}inline int getstr() {char c = getchar();for(; !islower(c); c = getchar());int len = 0;for(; islower(c); c = getchar())str[len++] = c;return len;}void Init() {scanf("%d%d", &n, &q);N = 0;int len;for(int i = 0; i < n; i++) {len = getstr();for(int j = 0; j < len; j++) {Id[N] = i;S[N++] = str[j];}Id[N] = -1;S[N++] = '$';}for(int i = 0; i < q; i++) {len = getstr();L[i] = N;for(int j = 0; j < len; j++) {Id[N] = -1;S[N++] = str[j];}R[i] = N;Id[N] = -1;S[N++] = '$';}S[N - 1] = 0;}int main() {Init();Work();return 0;}----------------------------------------------------------------------
2780: [Spoj]8093 Sevenk Love Oimaster
Time Limit:?1 Sec??Memory Limit:?128 MBSubmit:?581??Solved:?188
[Submit][Status][Discuss]
Description
??? ?Oimaster and sevenk love each other.
Input
There are two integers in the first line,?the number of strings n and the number of questions q.And n lines follow, each of them is a string describing oimaster's online talk.?And q lines follow, each of them is a question.n<=10000, q<=60000?the total length of n strings<=100000,?the total length of q question strings<=360000
Output
For each question, output the answer in one line.Sample Input
3 3abcabcabc
aaa
aafe
abc
a
ca
Sample Output
13
1
HINT
Source
?
轉載于:https://www.cnblogs.com/JSZX11556/p/5188453.html
總結
以上是生活随笔為你收集整理的BZOJ 2780: [Spoj]8093 Sevenk Love Oimaster( 后缀数组 + 二分 + RMQ + 树状数组 )的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 市场上杀好的兔肉多少钱一斤?
- 下一篇: 影视作品里团级指挥部里面都有哪些人。