QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#724755#9571. Border Jump 2FDUdululuWA 12ms144380kbC++208.7kb2024-11-08 14:54:492024-11-08 14:54:49

Judging History

你现在查看的是最新测评结果

  • [2024-11-08 14:54:49]
  • 评测
  • 测评结果:WA
  • 用时:12ms
  • 内存:144380kb
  • [2024-11-08 14:54:49]
  • 提交

answer

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <ctime>
#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 SAM {
    int n;
    int tot = 1, last = 1, cnt = 1;
    int sa[N], rk[N], ht[N];
    struct Node {
        int len, fa, edn;
        int ch[27], nxt[27];
        vector<int> tmp, son;
    } node[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;
        for (int i = 0; i <= tot; i++) {
            node[i].len = node[i].fa = node[i].edn = 0;
            for (int j = 0; j < 27; j++)
                node[i].ch[j] = node[i].nxt[j] = 0;
            node[i].son.clear();
            node[i].tmp.clear();
        }
        // clear 时先清空 node,再重置 tot 和 last
        tot = last = cnt = 1;
    }
    int extend(int x, int c) {
        int p = last, np = last = ++tot;
        node[np].len = node[p].len + 1;
        for (; p && (!node[p].ch[c]); p = node[p].fa)
            node[p].ch[c] = np;
        if (!p)
            node[np].fa = 1;
        else {
            int q = node[p].ch[c];
            if (node[q].len == node[p].len + 1)
                node[np].fa = q;
            else {
                int nq = ++tot;
                // 注意此处复制了结点 q, 若每个节点还要维护其他信息,注意清空或取舍
                node[nq] = node[q];
                node[nq].edn = 0;
                node[nq].len = node[p].len + 1;
                node[q].fa = node[np].fa = nq;
                for (; p && node[p].ch[c] == q; p = node[p].fa)
                    node[p].ch[c] = nq;
            }
        }
        node[np].edn = x;
        // the node of this prefix
        return np;
    }
    void dfs1(int x) {
        for (auto y : node[x].tmp) {
            dfs1(y);
            node[x].edn = max(node[x].edn, node[y].edn);
        }
    }
    void dfs2(int x) {
        if (node[x].son.size() == 0) {
            rk[node[x].edn] = cnt;
            sa[cnt] = node[x].edn;
            cnt++;
        }
        for (auto y : node[x].son)
            dfs2(y);
    }
    void build() {
        for (int i = 1; i <= tot; i++)
            node[node[i].fa].tmp.push_back(i);
        dfs1(1);
        for (int i = 1; i <= tot; i++) {
            int c = s[node[i].edn + node[node[i].fa].len] - 'a';
            node[node[i].fa].nxt[c] = i;
        }
        for (int i = 1; i <= tot; i++) {
            for (int j = 0; j < 27; j++)
                if (node[i].nxt[j]) {
                    node[i].son.push_back(node[i].nxt[j]);
                }
        }
        dfs2(1);
        for (int i = 0; i < K; i++)
            for (int j = 0; j <= n; j++)
                st[i][j] = n;
        get_ht();
        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]);
    }
    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;
        }
    }
    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;
            if (query(mid, x) >= len) {
                ans = mid;
                r = mid - 1;
            } else
                l = mid + 1;
        }
        return ans;
    }
    int findsuf(int x, int len) {
        int l = x, r = n, mid, ans = x;
        while (l <= r) {
            mid = (l + r) >> 1;
            if (query(mid, x) >= len) {
                ans = mid;
                l = mid + 1;
            } else
                r = mid - 1;
        }
        return ans;
    }
} sam;

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) {
    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(int T) {
    int sd, td;
    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] = '{';

    sam.init(m);
    for (int i = m; i >= 1; i--)
        sam.extend(i, s[i] - 'a');
    sam.build();

    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;
    build(rt[0], 1, m);
    for (int i = 1; i <= m; i++) {
        int x = sam.rk[i], d = i;
        if (i <= n + 1)
            d = 0;
        update(rt[i], rt[i - 1], 1, m, x, d);
    }

    int ans = 0;
    for (int i = 1; i <= n; i++) {
        int res = 0;
        int len = pl[i];
        while (true) {
            int l = sam.findpre(sam.rk[i], len);
            int r = sam.findsuf(sam.rk[i], len);
            int lim = m - (i + len) + 1; 
            int pos = query(rt[lim], 1, m, l, r);
            if (pos == 0)
                break;
            pos = m - pos + 1;
            len = pos - i + 1;
            res++;
            if (len == n)
                break;
        }
        int w = i + ((pl[i] + 1) / 2) - 1;
        int l = i, r = w, mid, pos = w, c = s[r] - '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;
        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(T);
    }
    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: 7ms
memory: 144380kb

input:

3
aaaa
abbaabba
xy

output:

3
4
0

result:

ok 3 number(s): "3 4 0"

Test #2:

score: 0
Accepted
time: 3ms
memory: 143856kb

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: 12ms
memory: 143860kb

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: -100
Wrong Answer
time: 7ms
memory: 143204kb

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
2
1
1
1
1
2
1
1
1
1
1
1
1
2
2
2
2
1
2
2
...

result:

wrong answer 131st numbers differ - expected: '1', found: '2'