QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#724198 | #9571. Border Jump 2 | FDUdululu | TL | 662ms | 24360kb | C++20 | 8.2kb | 2024-11-08 10:43:01 | 2024-11-08 10:43:03 |
Judging History
answer
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
using namespace std;
typedef long long ll;
const int N = 5e5 + 5; // |S|
const int M = 27; // max ASCII(s_i)
const int K = 20; // log N
char s[N];
struct SuffixArray {
int n, m = M;
int sa[N], rk[N], ht[N], tax[N], tmp[N];
int st[N][K], lg[N];
void init(int N) {
n = N;
for (int i = 0; i <= n; i++) {
sa[i] = rk[i] = ht[i] = 0;
tax[i] = tmp[i] = 0;
}
for (int i = 0; i < K; i++)
for (int j = 0; j <= n; j++)
st[i][j] = n;
m = M;
SA();
get_ht();
build();
}
void Qsort() {
for (int i = 0; i <= m; i++)
tax[i] = 0;
for (int i = 1; i <= n; i++)
tax[rk[i]]++;
for (int i = 1; i <= m; i++)
tax[i] += tax[i - 1];
for (int i = n; i >= 1; i--)
sa[tax[rk[tmp[i]]]--] = tmp[i];
}
int cmp(int x, int y, int w) {
return (tmp[x] == tmp[y] && tmp[x + w] == tmp[y + w]);
}
void SA() {
for (int i = 1; i <= n; i++) {
rk[i] = s[i] - 'a' + 1;
tmp[i] = i;
}
Qsort();
for (int w = 1; w <= n; w <<= 1) {
int p = 0;
for (int i = n - w + 1; i <= n; i++)
tmp[++p] = i;
for (int i = 1; i <= n; i++)
if (sa[i] > w)
tmp[++p] = sa[i] - w;
Qsort();
swap(tmp, rk);
rk[sa[1]] = p = 1;
for (int i = 2; i <= n; i++)
rk[sa[i]] = cmp(sa[i - 1], sa[i], w) ? p : ++p;
if (p == n)
break;
m = p;
}
}
void get_ht() { // ht[i] = lcp(sa[i], sa[i - 1])
for (int i = 1, k = 0; i <= n; i++) {
if (k)
--k;
// 多测记得防越界
// 或者 s[] 开两倍空间,清空后一半
// while ((i + k <= n && sa[rk[i] - 1] + k <= n) && s[i + k] == s[sa[rk[i] - 1] + k])
// k++;
while (s[i + k] == s[sa[rk[i] - 1] + k])
k++;
ht[rk[i]] = k;
}
}
void build() {
for (int i = 2; i <= n; i++) // index starts with 2
lg[i] = lg[i >> 1] + 1;
for (int i = 1; i <= n; i++)
st[i][0] = ht[i];
for (int i = 1; i < K; i++)
for (int j = 1; j + (1 << i) - 1 <= n; j++)
st[j][i] = min(st[j][i - 1], st[j + (1 << (i - 1))][i - 1]);
}
int query(int L, int R) { // lcp(s[i,n],s[j,n])
int l, r;
l = min(L, R) + 1;
r = max(L, R);
int t = lg[r - l + 1];
return min(st[l][t], st[r - (1 << t) + 1][t]);
}
int findpre(int x, int len) {
int l = 1, r = x, mid, ans = x;
while (l <= r) {
mid = (l + r) >> 1;
// cout << "@ " << l << " " << r << "\n";
if (query(mid, x) >= len) {
ans = mid;
r = mid - 1;
} else
l = mid + 1;
}
// cout << "@ " << ans << "\n";
return ans;
}
int findsuf(int x, int len) {
int l = x, r = n, mid, ans = x;
while (l <= r) {
mid = (l + r) >> 1;
// cout << "# " << l << " " << r << "\n";
if (query(mid, x) >= len) {
ans = mid;
l = mid + 1;
} else
r = mid - 1;
}
// cout << "# " << ans << "\n";
return ans;
}
} sa;
struct PAM {
int n;
char s[N];
int tot = 1, last = 1;
struct Node {
int len, fa, dep;
int ch[26];
} node[N];
void init() {
for (int i = 0; i <= n; i++)
s[i] = ' ';
for (int i = 0; i <= tot; i++) {
node[i].len = node[i].fa = node[i].dep = 0;
for (int j = 0; j < 26; j++)
node[i].ch[j] = 0;
}
n = 0;
tot = last = 1;
s[0] = '$';
node[0] = {0, 1};
node[1] = {-1, 0};
}
int getfail(int x) {
while (s[n - node[x].len - 1] != s[n])
x = node[x].fa;
return x;
}
void extend(int c) {
s[++n] = (char)(c + 'a');
int p = getfail(last);
if (!node[p].ch[c]) {
int np = ++tot;
node[np].len = node[p].len + 2;
node[np].fa = node[getfail(node[p].fa)].ch[c];
node[np].dep = node[node[np].fa].dep + 1;
node[p].ch[c] = np;
}
last = node[p].ch[c];
}
} pam;
struct Node {
int v, l, r;
} t[N << 5];
int rt[N], tot;
void pushup(int p) {
t[p].v = max(t[t[p].l].v, t[t[p].r].v);
}
void build(int& p, int l, int r) {
p = ++tot;
t[p] = {0, 0, 0};
if (l == r)
return;
int mid = (l + r) >> 1;
build(t[p].l, l, mid);
build(t[p].r, mid + 1, r);
pushup(p);
}
void update(int& p, int q, int l, int r, int x, int d) {
p = ++tot;
t[p] = t[q];
if (l == r) {
t[p].v = d;
return;
}
int mid = (l + r) >> 1;
if (x <= mid)
update(t[p].l, t[q].l, l, mid, x, d);
else
update(t[p].r, t[q].r, mid + 1, r, x, d);
pushup(p);
}
int query(int p, int l, int r, int x, int y) {
// cout << "$$$ " << l << " " << r << " " << x << " " << y << " " << t[p].v << "\n";
if (x <= l && r <= y)
return t[p].v;
int mid = (l + r) >> 1;
int ans = 0;
if (x <= mid)
ans = max(ans, query(t[p].l, l, mid, x, y));
if (y > mid)
ans = max(ans, query(t[p].r, mid + 1, r, x, y));
return ans;
}
int pl[N], sum[N][26];
void solve() {
string t;
cin >> t;
int n = t.size(), m = 2 * n + 1;
t = " " + t;
for (int i = 1; i <= n; i++) {
s[i] = s[m - i + 1] = t[i];
for (int j = 0; j < 26; j++)
sum[i][j] = sum[i - 1][j];
sum[i][s[i] - 'a']++;
}
s[n + 1] = '{';
sa.init(m);
pam.init();
for (int i = n; i >= 1; i--) {
pam.extend(s[i] - 'a');
int len = pam.node[pam.last].len;
pl[i] = len;
}
tot = 0;
// cout << "HI\n";
build(rt[0], 1, m);
for (int i = 1; i <= m; i++) {
int x = sa.rk[i], d = i;
if (i <= n + 1)
d = 0;
// cout << i << " " << x << " " << d << "\n";
update(rt[i], rt[i - 1], 1, m, x, d);
}
// for (int i = 1; i <= m; i++)
// cout << sa.sa[i] << " ";
// cout << "\n";
// cout << query(rt[11], 1, m, 2, 5) << "\n";
// return;
int ans = 0;
for (int i = 1; i <= n; i++) {
int res = 0;
int len = pl[i];
while (true) {
int l = sa.findpre(sa.rk[i], len);
int r = sa.findsuf(sa.rk[i], len);
// cout << "? " << sa.rk[i] << " " << len << " " << l << " " << r << "\n";
int lim = m - (i + len) + 1; //?
int pos = query(rt[lim], 1, m, l, r);
// cout << "?? " << lim << " " << i << " " << len << " " << pos << "\n";
if (pos == 0)
break;
pos = m - pos + 1;
len = pos - i + 1;
res++;
}
int w = i + ((pl[i] + 1) / 2) - 1;
int l = i, r = w, mid, pos = w, c = s[r] - 'a';
// cout << "! " << i << " " << res << " " << w << " " << (char)(c + 'a') << " ";
while (l <= r) {
mid = (l + r) >> 1;
if (sum[w][c] - sum[mid - 1][c] == (w - mid + 1)) {
pos = mid;
r = mid - 1;
} else
l = mid + 1;
}
pos = pos - i + 1;
// cout << pos << "\n";
res += (pos - 1);
res += pl[i] - 2 * (pos - 1) - 1;
ans = max(ans, res);
}
cout << ans << "\n";
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int T = 1;
cin >> T;
while (T--) {
solve();
}
return 0;
}
/*
5
aaaa
abbaabba
xy
aabaa
aabcaa
2
bvvvb
abcvvvcba
*/
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 3ms
memory: 23988kb
input:
3 aaaa abbaabba xy
output:
3 4 0
result:
ok 3 number(s): "3 4 0"
Test #2:
score: 0
Accepted
time: 10ms
memory: 22300kb
input:
15 eeee ooom bbcb yyaa ssdn wgww hrhr exer hcch qyyy lppa ocvo orxr lrjj pztv
output:
3 2 1 1 1 1 1 1 2 2 1 1 1 1 0
result:
ok 15 numbers
Test #3:
score: 0
Accepted
time: 37ms
memory: 24052kb
input:
52 eeeee oooom bbbcb yyyaa sssdn wwgww hhrhr eexer hhcch qqyyy llppa oocvo oorxr llrjj ppztv tnttt vnvvn hthhp jzjzj nrnrr gqgqt uruyu cdchd djdhh ktkfy piipp zaaza uffuq bvvvb hkkkk pcccj qccpq wqqaq appgg cxxvg ewfee peupe odfof kdpkh zotoz yzkzz irtrt vxyxi dlood akrrk nsbbb rdjjc bfexb uxsex ise...
output:
4 3 2 2 2 2 1 1 2 2 1 1 1 1 1 2 2 1 2 1 1 1 1 1 1 2 2 2 3 3 2 1 1 1 1 1 1 1 1 2 1 1 1 1 2 2 1 1 1 1 1 0
result:
ok 52 numbers
Test #4:
score: 0
Accepted
time: 150ms
memory: 24360kb
input:
203 eeeeee ooooom bbbbcb yyyyaa ssssdn wwwgww hhhrhr eeexer hhhcch qqqyyy lllppa ooocvo ooorxr lllrjj pppztv ttnttt vvnvvn hhthhp jjzjzj nnrnrr ggqgqt uuruyu ccdchd ddjdhh kktkfy ppiipp zzaaza uuffuq bbvvvb hhkkkk ppcccj qqccpq wwqqaq aappgg ccxxvg eewfee ppeupe oodfof kkdpkh zzotoz yyzkzz iirtrt vv...
output:
5 4 3 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 3 2 2 3 3 2 1 1 1 1 2 1 1 1 2 1 1 1 1 2 2 1 1 1 1 1 1 3 3 2 3 2 2 1 1 1 1 2 2 2 2 2 1 1 1 1 1 1 2 1 1 1 1 1 1 2 1 2 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 3 3 3 4 4 3 2 2 2 2 1 1 1 1 1 2 1 1 1 2 2 1 1 1 1 1 1 2 1 2 1 1 1 1 1 1 2 1 1 1 1 1 1 1 2 2 2 2 1 2 2 ...
result:
ok 203 numbers
Test #5:
score: 0
Accepted
time: 662ms
memory: 22004kb
input:
877 eeeeeee oooooom bbbbbcb yyyyyaa sssssdn wwwwgww hhhhrhr eeeexer hhhhcch qqqqyyy llllppa oooocvo oooorxr llllrjj ppppztv tttnttt vvvnvvn hhhthhp jjjzjzj nnnrnrr gggqgqt uuuruyu cccdchd dddjdhh kkktkfy pppiipp zzzaaza uuuffuq bbbvvvb hhhkkkk pppcccj qqqccpq wwwqqaq aaappgg cccxxvg eeewfee pppeupe ...
output:
6 5 4 4 4 3 3 3 3 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 2 3 2 2 3 3 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 3 3 2 3 2 2 2 2 2 2 3 2 2 2 2 1 1 1 1 1 2 2 1 1 1 1 1 1 2 1 2 1 1 1 1 1 1 3 3 3 2 2 2 2 2 2 2 4 3 3 4 4 3 2 2 2 2 2 1 1 1 1 2 1 1 1 2 2 1 1 1 1 1 1 2 2 2 2 1 1 1 1 1 2 1 1 1 1 1 1 1 3 2 2 2 1 2 2 ...
result:
ok 877 numbers
Test #6:
score: -100
Time Limit Exceeded
input:
4140 eeeeeeee ooooooom bbbbbbcb yyyyyyaa ssssssdn wwwwwgww hhhhhrhr eeeeexer hhhhhcch qqqqqyyy lllllppa ooooocvo ooooorxr lllllrjj pppppztv ttttnttt vvvvnvvn hhhhthhp jjjjzjzj nnnnrnrr ggggqgqt uuuuruyu ccccdchd ddddjdhh kkkktkfy ppppiipp zzzzaaza uuuuffuq bbbbvvvb hhhhkkkk ppppcccj qqqqccpq wwwwqqa...