kyopro_library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub dyktr06/kyopro_library

:heavy_check_mark: test/library_checker/string/runenumerate.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/runenumerate"
#include <bits/stdc++.h>
using namespace std;

#include "../../../lib/string/run_enumerate.hpp"

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string s; cin >> s;
    auto ans = run_enumerate(s);
    cout << ans.size() << '\n';
    for(auto [len, l, r] : ans){
        cout << len << ' ' << l << ' ' << r << '\n';
    }
}
#line 1 "test/library_checker/string/runenumerate.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/runenumerate"
#include <bits/stdc++.h>
using namespace std;

#line 2 "lib/string/run_enumerate.hpp"

/**
 * @brief Run Enumerate
 * @docs docs/string/run_enumerate.md
 * @see https://pazzle1230.hatenablog.com/entry/2019/11/27/234632
 */

#line 2 "lib/string/z_algorithm.hpp"

/**
 * @brief Z Algorithm
 * @docs docs/string/z_algorithm.md
 */

template <typename T>
vector<int> z_algorithm(const T &s) {
    int n = s.size();
    vector<int> res(n, 0);
    for(int i = 1, j = 0; i < n; ++i){
        if(i + res[i - j] < j + res[j]){
            res[i] = res[i - j];
        } else{
            res[i] = max(j + res[j] - i, 0);
            while(i + res[i] < n && s[i + res[i]] == s[res[i]]) ++res[i];
            j = i;
        }
    }
    res[0] = n;
    return res;
}
#line 10 "lib/string/run_enumerate.hpp"

vector<tuple<int, int, int>> run_enumerate(const string &s){
    int n = s.size();
    vector<tuple<int, int, int>> res;
    auto dfs = [&](auto &self, int l, int r) -> void {
        if(r - l < 2){
            return;
        }
        int mid = (l + r) / 2;
        self(self, l, mid);
        self(self, mid, r);

        string ns = s.substr(l, r - l);
        int lenl = mid - l, lenr = r - mid;
        string sl = s.substr(l, lenl);
        reverse(sl.begin(), sl.end());
        string sr = s.substr(mid, lenr);
        sr += ns;
        reverse(ns.begin(), ns.end());
        sl += ns;
        auto zl = z_algorithm(sl);
        auto zr = z_algorithm(sr);
        {
            for(int i = l; i < mid; i++){
                // [i, mid) を周期
                int len = mid - i;
                int nl = i, nr = mid;
                if(i > l) nl = max(l, nl - zl[len]);
                nr = min(r, nr + zr[lenr + (i - l)]);
                if(nr - nl >= len * 2){
                    if(nl >= 1 && s[nl - 1] == s[nl - 1 + len]){
                        continue;
                    }
                    if(nr < n && s[nr] == s[nr - len]){
                        continue;
                    }
                    res.emplace_back(nl, nr, len);
                }
            }
        }
        {
            for(int i = mid + 1; i <= r; i++){
                // [mid, i) を周期
                int len = i - mid;
                int nl = mid, nr = i;
                if(i < r) nr = min(r, nr + zr[len]);
                nl = max(l, nl - zl[lenl + (r - i)]);
                if(nr - nl >= len * 2){
                    if(nl >= 1 && s[nl - 1] == s[nl - 1 + len]){
                        continue;
                    }
                    if(nr < n && s[nr] == s[nr - len]){
                        continue;
                    }
                    res.emplace_back(nl, nr, len);
                }
            }
        }
    };
    dfs(dfs, 0, n);
    sort(res.begin(), res.end());
    vector<tuple<int, int, int>> ans;
    int pl = -1, pr = -1;
    for(auto [l, r, len] : res){
        if(l == pl && r == pr){
            continue;
        }
        pl = l, pr = r;
        ans.emplace_back(len, l, r);
    }
    sort(ans.begin(), ans.end());
    return ans;
}
#line 6 "test/library_checker/string/runenumerate.test.cpp"

int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    string s; cin >> s;
    auto ans = run_enumerate(s);
    cout << ans.size() << '\n';
    for(auto [len, l, r] : ans){
        cout << len << ' ' << l << ' ' << r << '\n';
    }
}
Back to top page