結果

問題 No.2454 Former < Latter
ユーザー tamura-uptamura-up
提出日時 2023-09-01 22:33:12
言語 C++17
(gcc 12.3.0 + boost 1.83.0)
結果
WA  
実行時間 -
コード長 15,560 bytes
コンパイル時間 3,248 ms
コンパイル使用メモリ 237,604 KB
実行使用メモリ 10,840 KB
最終ジャッジ日時 2024-06-11 04:29:31
合計ジャッジ時間 4,654 ms
ジャッジサーバーID
(参考情報)
judge3 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
6,812 KB
testcase_01 WA -
testcase_02 WA -
testcase_03 AC 15 ms
7,132 KB
testcase_04 WA -
testcase_05 WA -
testcase_06 WA -
testcase_07 WA -
testcase_08 WA -
testcase_09 AC 18 ms
6,944 KB
testcase_10 WA -
testcase_11 WA -
testcase_12 WA -
testcase_13 AC 13 ms
7,252 KB
testcase_14 AC 14 ms
7,128 KB
testcase_15 WA -
testcase_16 AC 32 ms
7,296 KB
testcase_17 AC 41 ms
6,944 KB
testcase_18 WA -
testcase_19 AC 37 ms
10,840 KB
testcase_20 AC 36 ms
9,432 KB
testcase_21 WA -
testcase_22 WA -
testcase_23 AC 23 ms
6,940 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author
 */

//@formatter:off
#pragma GCC optimize("Ofast")
#include <bits/stdc++.h>
using namespace std;


#include <algorithm>
#include <cassert>
#include <numeric>
#include <string>
#include <vector>

namespace atcoder {

namespace internal {

std::vector<int> sa_naive(const std::vector<int>& s) {
    int n = int(s.size());
    std::vector<int> sa(n);
    std::iota(sa.begin(), sa.end(), 0);
    std::sort(sa.begin(), sa.end(), [&](int l, int r) {
        if (l == r) return false;
        while (l < n && r < n) {
            if (s[l] != s[r]) return s[l] < s[r];
            l++;
            r++;
        }
        return l == n;
    });
    return sa;
}

std::vector<int> sa_doubling(const std::vector<int>& s) {
    int n = int(s.size());
    std::vector<int> sa(n), rnk = s, tmp(n);
    std::iota(sa.begin(), sa.end(), 0);
    for (int k = 1; k < n; k *= 2) {
        auto cmp = [&](int x, int y) {
            if (rnk[x] != rnk[y]) return rnk[x] < rnk[y];
            int rx = x + k < n ? rnk[x + k] : -1;
            int ry = y + k < n ? rnk[y + k] : -1;
            return rx < ry;
        };
        std::sort(sa.begin(), sa.end(), cmp);
        tmp[sa[0]] = 0;
        for (int i = 1; i < n; i++) {
            tmp[sa[i]] = tmp[sa[i - 1]] + (cmp(sa[i - 1], sa[i]) ? 1 : 0);
        }
        std::swap(tmp, rnk);
    }
    return sa;
}

template <int THRESHOLD_NAIVE = 10, int THRESHOLD_DOUBLING = 40>
std::vector<int> sa_is(const std::vector<int>& s, int upper) {
    int n = int(s.size());
    if (n == 0) return {};
    if (n == 1) return {0};
    if (n == 2) {
        if (s[0] < s[1]) {
            return {0, 1};
        } else {
            return {1, 0};
        }
    }
    if (n < THRESHOLD_NAIVE) {
        return sa_naive(s);
    }
    if (n < THRESHOLD_DOUBLING) {
        return sa_doubling(s);
    }

    std::vector<int> sa(n);
    std::vector<bool> ls(n);
    for (int i = n - 2; i >= 0; i--) {
        ls[i] = (s[i] == s[i + 1]) ? ls[i + 1] : (s[i] < s[i + 1]);
    }
    std::vector<int> sum_l(upper + 1), sum_s(upper + 1);
    for (int i = 0; i < n; i++) {
        if (!ls[i]) {
            sum_s[s[i]]++;
        } else {
            sum_l[s[i] + 1]++;
        }
    }
    for (int i = 0; i <= upper; i++) {
        sum_s[i] += sum_l[i];
        if (i < upper) sum_l[i + 1] += sum_s[i];
    }

    auto induce = [&](const std::vector<int>& lms) {
        std::fill(sa.begin(), sa.end(), -1);
        std::vector<int> buf(upper + 1);
        std::copy(sum_s.begin(), sum_s.end(), buf.begin());
        for (auto d : lms) {
            if (d == n) continue;
            sa[buf[s[d]]++] = d;
        }
        std::copy(sum_l.begin(), sum_l.end(), buf.begin());
        sa[buf[s[n - 1]]++] = n - 1;
        for (int i = 0; i < n; i++) {
            int v = sa[i];
            if (v >= 1 && !ls[v - 1]) {
                sa[buf[s[v - 1]]++] = v - 1;
            }
        }
        std::copy(sum_l.begin(), sum_l.end(), buf.begin());
        for (int i = n - 1; i >= 0; i--) {
            int v = sa[i];
            if (v >= 1 && ls[v - 1]) {
                sa[--buf[s[v - 1] + 1]] = v - 1;
            }
        }
    };

    std::vector<int> lms_map(n + 1, -1);
    int m = 0;
    for (int i = 1; i < n; i++) {
        if (!ls[i - 1] && ls[i]) {
            lms_map[i] = m++;
        }
    }
    std::vector<int> lms;
    lms.reserve(m);
    for (int i = 1; i < n; i++) {
        if (!ls[i - 1] && ls[i]) {
            lms.push_back(i);
        }
    }

    induce(lms);

    if (m) {
        std::vector<int> sorted_lms;
        sorted_lms.reserve(m);
        for (int v : sa) {
            if (lms_map[v] != -1) sorted_lms.push_back(v);
        }
        std::vector<int> rec_s(m);
        int rec_upper = 0;
        rec_s[lms_map[sorted_lms[0]]] = 0;
        for (int i = 1; i < m; i++) {
            int l = sorted_lms[i - 1], r = sorted_lms[i];
            int end_l = (lms_map[l] + 1 < m) ? lms[lms_map[l] + 1] : n;
            int end_r = (lms_map[r] + 1 < m) ? lms[lms_map[r] + 1] : n;
            bool same = true;
            if (end_l - l != end_r - r) {
                same = false;
            } else {
                while (l < end_l) {
                    if (s[l] != s[r]) {
                        break;
                    }
                    l++;
                    r++;
                }
                if (l == n || s[l] != s[r]) same = false;
            }
            if (!same) rec_upper++;
            rec_s[lms_map[sorted_lms[i]]] = rec_upper;
        }

        auto rec_sa =
            sa_is<THRESHOLD_NAIVE, THRESHOLD_DOUBLING>(rec_s, rec_upper);

        for (int i = 0; i < m; i++) {
            sorted_lms[i] = lms[rec_sa[i]];
        }
        induce(sorted_lms);
    }
    return sa;
}

}  // namespace internal

std::vector<int> suffix_array(const std::vector<int>& s, int upper) {
    assert(0 <= upper);
    for (int d : s) {
        assert(0 <= d && d <= upper);
    }
    auto sa = internal::sa_is(s, upper);
    return sa;
}

template <class T> std::vector<int> suffix_array(const std::vector<T>& s) {
    int n = int(s.size());
    std::vector<int> idx(n);
    iota(idx.begin(), idx.end(), 0);
    sort(idx.begin(), idx.end(), [&](int l, int r) { return s[l] < s[r]; });
    std::vector<int> s2(n);
    int now = 0;
    for (int i = 0; i < n; i++) {
        if (i && s[idx[i - 1]] != s[idx[i]]) now++;
        s2[idx[i]] = now;
    }
    return internal::sa_is(s2, now);
}

std::vector<int> suffix_array(const std::string& s) {
    int n = int(s.size());
    std::vector<int> s2(n);
    for (int i = 0; i < n; i++) {
        s2[i] = s[i];
    }
    return internal::sa_is(s2, 255);
}

template <class T>
std::vector<int> lcp_array(const std::vector<T>& s,
                           const std::vector<int>& sa) {
    int n = int(s.size());
    assert(n >= 1);
    std::vector<int> rnk(n);
    for (int i = 0; i < n; i++) {
        rnk[sa[i]] = i;
    }
    std::vector<int> lcp(n - 1);
    int h = 0;
    for (int i = 0; i < n; i++) {
        if (h > 0) h--;
        if (rnk[i] == 0) continue;
        int j = sa[rnk[i] - 1];
        for (; j + h < n && i + h < n; h++) {
            if (s[j + h] != s[i + h]) break;
        }
        lcp[rnk[i] - 1] = h;
    }
    return lcp;
}

std::vector<int> lcp_array(const std::string& s, const std::vector<int>& sa) {
    int n = int(s.size());
    std::vector<int> s2(n);
    for (int i = 0; i < n; i++) {
        s2[i] = s[i];
    }
    return lcp_array(s2, sa);
}

template <class T> std::vector<int> z_algorithm(const std::vector<T>& s) {
    int n = int(s.size());
    if (n == 0) return {};
    std::vector<int> z(n);
    z[0] = 0;
    for (int i = 1, j = 0; i < n; i++) {
        int& k = z[i];
        k = (j + z[j] <= i) ? 0 : std::min(j + z[j] - i, z[i - j]);
        while (i + k < n && s[k] == s[i + k]) k++;
        if (j + z[j] < i + z[i]) j = i;
    }
    z[0] = n;
    return z;
}

std::vector<int> z_algorithm(const std::string& s) {
    int n = int(s.size());
    std::vector<int> s2(n);
    for (int i = 0; i < n; i++) {
        s2[i] = s[i];
    }
    return z_algorithm(s2);
}

}  // namespace atcoder


//@formatter:off
#define rep(i, n) for (int i = 0; i < (n); ++i)
#define drep(i, n) for (int i = (n)-1; i >= 0; --i)
#define srep(i, s, t) for (int i = s; i < t; ++i)
#define rng(a) a.begin(), a.end()
#define rrng(a) a.rbegin(), a.rend()
using ll = long long;
using P = pair<ll, ll>;
using VI = vector<int>;
using VVI = vector<VI>;
using VVVI = vector<VVI>;
using VVVVI = vector<VVVI>;
using VL = vector<ll>;
using VVL = vector<VL>;
using VVVL = vector<VVL>;
using VVVVL = vector<VVVL>;
using VP = vector<P>;
using VVP = vector<vector<P>>;
using VS = vector<string>;
using VC = vector<char>;
using VVC = vector<vector<char>>;
using VD = vector<double>;
using VVD = vector<vector<double>>;
using VVVD = vector<VVD>;
using I_I = pair<int, int>;
const int INF = (int)1e9 + 10;         // int max > 2*10^9
const long long INFL = (ll)2e18 + 10;  // ll max > 9*10^18

const int JU_5 = 100000;
const int JU_6 = 1000000;
const ll JU_9 = 1000000000;
const ll JU_18 = JU_9*JU_9;


#define YES cout << "YES" << endl
#define NO cout << "NO" << endl
#define Yes cout << "Yes" << endl
#define No cout << "No" << endl

template <typename T, typename C>
pair<T,C> operator+(const pair<T,C> &a, const pair<T,C> &b) { return make_pair(a.first + b.first, a.second + b.second); }
template <typename T, typename C>
pair<T,C> operator-(const pair<T,C> &a, const pair<T,C> &b) { return make_pair(a.first - b.first, a.second - b.second); }
template <typename T, typename C>
pair<T,C> operator*(const pair<T,C> &a, const pair<T,C> &b) { return make_pair(a.first * b.first, a.second * b.second); }
template <typename T, typename C>
pair<T,C> operator/(const pair<T,C> &a, const pair<T,C> &b) { return make_pair(a.first / b.first, a.second / b.second); }


// #define MOD 1000000007
#define MOD 998244353

#define pmod(x,y) ((x%y)+y)%y

/********** libs **********/
//@formatter:off
// jhelper 用変数
ostream *__cout;
istream *__cin;

void _init_io(std::istream &cin, std::ostream &cout) {
    // 入出力高速化用
    ios::sync_with_stdio(false); cin.tie(nullptr);
    cout << std::setprecision(30);
    // jhelper 用
    __cout = &cout; __cin = &cin;
}

//@formatter:off
/* デバッグ用 出力 */
template<typename T>
ostream &operator<<(ostream &os, const deque<T> &vec) { os << "deq["; for (auto v: vec) os << v << ","; os << "]"; return os; }

template<typename T>
ostream &operator<<(ostream &os, const set<T> &vec) { os << "{"; for (auto v: vec) os << v << ","; os << "}"; return os; }

template<typename T>
ostream &operator<<(ostream &os, const unordered_set<T> &vec) { os << "{"; for (auto v: vec) os << v << ","; os << "}"; return os; }

template<typename T>
ostream &operator<<(ostream &os, const multiset<T> &vec) { os << "{"; for (auto v: vec) os << v << ","; os << "}"; return os; }

template<typename T>
ostream &operator<<(ostream &os, const unordered_multiset<T> &vec) { os << "{"; for (auto v: vec) os << v << ","; os << "}"; return os; }

template<typename T1, typename T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &pa) { os << "(" << pa.first << "," << pa.second << ")"; return os; }
template<typename TK, typename TV>
ostream &operator<<(ostream &os, const map<TK, TV> &mp) { os << "{"; for (auto v: mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }

template<typename TK, typename TV>
ostream &operator<<(ostream &os, const unordered_map<TK, TV> &mp) { os << "{"; for (auto v: mp) os << v.first << "=>" << v.second << ","; os << "}"; return os; }

// print like python
// src: https://qiita.com/Lily0727K/items/06cb1d6da8a436369eed
/////////////////////////////////////////////////////////
void print() { *__cout << '\n'; }
template<class Head, class... Tail>
void print(Head &&head, Tail &&... tail) { *__cout << head; if (sizeof...(tail) != 0) *__cout << " "; print(forward<Tail>(tail)...); }
template<class T>
void print(vector<T> &vec) { for (auto &a: vec) { *__cout << a; if (&a != &vec.back()) *__cout << " "; } *__cout << '\n'; }
template<class T>
void print(vector<vector<T>> &df) { for (auto &vec: df) { print(vec); } }

// endl なし
void Print() {}
template<class Head, class... Tail>
void Print(Head &&head, Tail &&... tail) { *__cout << head; if (sizeof...(tail) != 0) *__cout << " "; Print(forward<Tail>(tail)...); }
template<class T>
void Print(vector<T> &vec) { for (auto &a: vec) { *__cout << a; if (&a != &vec.back()) *__cout << " "; } }
//@formatter:off
/*
 * org: https://atcoder.jp/contests/abc213/submissions/24901856
 * jhelper で使用するため, 全部 cin での入力にしている. (現状のレベルでは困らないので)
 */
template<class T> void scan(T& a){ *__cin >> a; }
template<class T> void scan(vector<T>&);
template<class T, class L> void scan(pair<T, L>&);
template<class T> void scan(vector<T>& a){ for(auto&& i : a) scan(i); }
template<class T, class L> void scan(pair<T, L>& p){ scan(p.first); scan(p.second); }
template<class T, size_t size> void scan(T (&a)[size]){ for(auto&& i : a) scan(i); }
void in(){}
template <class... T> void in(T&... a){ (void)initializer_list<int>{ (scan(a), 0)... }; }

#define let_v(type,name,...) vector<type>name(__VA_ARGS__)
#define let_V(type,name,size) vector<type>name(size);in(name)
#define let_vv(type,name,h,...) vector<vector<type>>name(h,vector<type>(__VA_ARGS__))
#define let_VV(type,name,h,w) vector<vector<type>>name(h,vector<type>(w));in(name)
#define let_vvv(type,name,h,w,...) vector<vector<vector<type>>>name(h,vector<vector<type>>(w,vector<type>(__VA_ARGS__)))
#define let_vvvv(type,name,h,w,x,...) vector<vector<vector<vector<type>>>>name(h,vector<vector<vector<type>>>(w,vector<vector<type>>(x,vector<type>(__VA_ARGS__))))
#define let_vvvvv(type,name,h,w,x,y,...) vector<vector<vector<vector<vector<type>>>>>name(h,vector<vector<vector<vector<type>>>>(w,vector<vector<vector<type>>>(x,vector<vector<type>>(y,vector<type>(__VA_ARGS__)))))

/* string 入力を vector<char> で受け取るみたいな */
vector<char> let_CharVec() { string s; *__cin >> s; return {s.begin(), s.end()}; }

//@formatter:off
//ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
ll lcm(ll a, ll b) { return a / gcd(a, b) * b; }

template <class T, class C>
bool chmax(T& a, C b) { if (a < b) { a = b; return true; } return false; }
template <class T, class C>
bool chmin(T& a, C b) { if (a > b) { a = b; return true; } return false; }

template <class T>
T sum(const vector<T>& v) { T res = 0; for (size_t i = 0; i < v.size(); ++i) res += v[i]; return res; }

//template <class T, class C>
//T min(T a, C b) { return a <= b ? a : T(b); }
//
//template <class T, class C>
//T max(T a, C b) { return a >= b ? a : T(b); }

template<class T>
vector<pair<T, int>> idx_pair(vector<T> &vals) { vector<pair<T, int>> ans; rep(i, vals.size()) { ans.emplace_back(vals[i], i); } return ans; }

template<typename T>
int argmax(vector<T> &vals){ if(vals.size()==0)return -1; int res=0; for(int i = 1;i<vals.size();i++){ if(vals[i]>vals[res])res=i; } return res; }

template<typename T>
int argmin(vector<T> &vals){ if(vals.size()==0)return -1; int res=0; for(int i = 1;i<vals.size();i++){ if(vals[i]<vals[res])res=i; } return res; }


// add other source
// #include "../library/graph/UnionFind.cpp"
// #include "../library/others/Zaatsu.cpp"
// #include "../library/graph/template.cpp"

// utils
// #include "../library/mint.cpp"
// #include "../library/string/utils.cpp"
// #include "../library/math/utils.cpp"
/**************************/

class unko {
public:
void solve(std::istream &cin, std::ostream &cout) { _init_io(cin, cout); int t = 1;
    cin >> t;
    while (t--) _solve(cin, cout); }
//@formatter:on

    void _solve(std::istream &cin, std::ostream &cout) {
        // code
        int n;
        string s;
        cin >> n >> s;
        auto res = atcoder::suffix_array(s);
        auto z = atcoder::z_algorithm(s);
//        print(res);
//        print(z);
        ll tot = 0;
        bool flg = false;
        rep(i, n) {
            int idx = res[i];
            if (idx == 0)flg = true;
            else if (flg) tot++;
        }
        drep(i, n) {
            if (i <= n / 2)break;
            if (z[i] == n - i)tot++;
        }
        print(tot);


    }

};


int main() {
	unko solver;
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
	return 0;
}
0