這個題確實思維方向非常重要。
如果用尾碼數組做,就轉化為區間眾數,一臉不可做。(當然莫對+堆還是可以的。。)
這個題應該用尾碼自動機或者尾碼樹來做。這樣問題就是子樹眾數,就可以用線段樹合并一個log搞定。(為什麼我一個log比別人一個log+一個根號還慢啊)
#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>#include<vector>#define rep(i,a,b) for(int i=a;i<=b;++i)#define erp(i,a,b) for(int i=a;i>=b;--i)#define LL long longusing namespace std;const int MAXN = 500005;const int MAXS = 1230000;int N, M;char s[MAXN];int ch[MAXS][27], fa[MAXS], ml[MAXS], anc[21][MAXS], pos[MAXN], rt[MAXS], que[MAXS];int tot = 1, last = 1;inline void extend(int c){int p = last;int np = last = ++tot;ml[np] = ml[p] + 1;while (p&&!ch[p][c]) ch[p][c] = np, p = fa[p];if (!p) { fa[np] = 1; return; }int q = ch[p][c];if (ml[p]+1 == ml[q]) fa[np] = q;else {int nq = ++tot; ml[nq] = ml[p]+1;memcpy(ch[nq], ch[q], sizeof ch[q]);fa[nq] = fa[q];fa[np] = fa[q] = nq;while (ch[p][c]==q) ch[p][c] = nq, p = fa[p];}}inline int getpos(int l, int r){int len = r-l+1, p = pos[r];erp(i,20,0) if(ml[anc[i][p]] >= len) p = anc[i][p];return p;}void toposort(){static int ws[MAXS];rep(i, 1, tot) ws[ml[i]] ++;rep(i, 1, tot) ws[i] += ws[i-1];rep(i, 1, tot) que[ws[ml[i]]--] = i;}int ncnt;#define lch(x) tr[x].lch#define rch(x) tr[x].rchstruct info { int mx, id; };struct Node {info t;int lch, rch;} tr[MAXS*22];info operator | (const info&a, const info&b){if (a.mx > b.mx) return a;if (a.mx < b.mx) return b;return a.id < b.id ? a : b;}void ins(int&p, int v, int l=1, int r=M){if (!p) p = ++ncnt;if (l==r) { tr[p].t.mx ++, tr[p].t.id = l; return; }int mid = (l+r)>>1;if (v<=mid) ins(lch(p), v, l, mid);else ins(rch(p), v, mid+1, r);tr[p].t = tr[lch(p)].t | tr[rch(p)].t;}int Merge(int x, int y, int l=1, int r=M){if (!x||!y) return x|y;int z = ++ncnt;if (l==r) {tr[z].t = (info){tr[x].t.mx+tr[y].t.mx, l};return z;}int mid = (l+r)>>1;lch(z) = Merge(lch(x), lch(y), l, mid);rch(z) = Merge(rch(x), rch(y), mid+1, r);tr[z].t = tr[lch(z)].t | tr[rch(z)].t;return z;}info ask(int p, int L, int R, int l=1, int r=M){if (!p) return (info){0,0};if (l>=L && r<=R) return tr[p].t;int mid = (l+r)>>1;if (R<=mid) return ask(lch(p), L, R, l, mid);if (L>mid) return ask(rch(p), L, R, mid+1, r);return ask(lch(p), L, R, l, mid) | ask(rch(p), L, R, mid+1, r);}void init(){toposort();erp(i,tot,1){int u = que[i];if (fa[u]) rt[fa[u]] = Merge(rt[fa[u]], rt[u]);}rep(i,1,tot) anc[0][i] = fa[i];rep(i,1,20) rep(j,1,tot) anc[i][j] = anc[i-1][ anc[i-1][j] ];}int main(){scanf("%s", s+1);N = strlen(s+1);rep(i,1,N) extend(s[i]-'a'), pos[i] = last;extend(26);scanf("%d", &M);rep(i, 1, M){scanf("%s", s+1);for (int j = 1; s[j]; ++j)extend(s[j]-'a'), ins(rt[last], i);extend(26);}init();int Q, a, b, l, r, p;scanf("%d", &Q);while (Q--){scanf("%d%d%d%d", &a, &b, &l, &r);p = getpos(l, r);info tmp = ask(rt[p], a, b);if (tmp.mx == 0) printf("%d 0\n", a);else printf("%d %d\n", tmp.id, tmp.mx);}return 0;}