chenfy27的刷题记录

导航

abc284F 前缀+逆序+后缀

题面:给一个长度为2n的字符串T,问是否存在长度为n的字符串S,满足:T = S的前缀 + 整串S逆序 + S的后缀。
范围:n<=1e6

思路:字符串哈希,枚举S的起点逐一判断,如果前i个字符加后n-i个字符组成的长为n的字符串,正好和中间串的逆序相同,则为解。

#include <bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;

i64 b1 = 433, m1 = 1000000433;
i64 b2 = 439, m2 = 1000000439;
std::vector<i64> p1, p2;
struct hval {
    i64 h1, h2, d;
    hval(i64 a=0, i64 b=0, i64 c=0):h1(a), h2(b), d(c) {}
    bool operator==(const hval &rhs) const {
        return h1 == rhs.h1 && h2 == rhs.h2 && d == rhs.d;
    }
    friend hval operator+(const hval &a, const hval &b) {
        hval res;
        res.h1 = a.h1 * p1[b.d] % m1; res.h1 += b.h1; res.h1 %= m1;
        res.h2 = a.h2 * p2[b.d] % m2; res.h2 += b.h2; res.h2 %= m2;
        res.d = a.d + b.d;
        return res;
    }
};

struct StrHash {
    std::vector<i64> h1, h2;
    void init(int n) {
        p1.assign(n + 1, 1);
        p2.assign(n + 1, 1);
        for (int i = 1; i <= n; i++) {
            p1[i] = p1[i - 1] * 433; p1[i] %= m1;
            p2[i] = p2[i - 1] * 439; p2[i] %= m2;
        }
    }
    template<typename InputIt>
    void build(InputIt st, InputIt ed) {
        size_t d = std::distance(st, ed);
        h1.assign(d + 2, 1);
        h2.assign(d + 2, 1);
        for (int i = 1; i <= d; i++) {
            h1[i] = h1[i - 1] * 433 + st[i - 1]; h1[i] %= m1;
            h2[i] = h2[i - 1] * 439 + st[i - 1]; h2[i] %= m2;
        }
    }
    hval get(int l, int r) {
        i64 d = r - l;
        i64 x = h1[r] - h1[l] * p1[d]; x %= m1; if (x < 0) x += m1;
        i64 y = h2[r] - h2[l] * p2[d]; y %= m2; if (y < 0) y += m2;
        return {x, y, d};
    }
    hval get(std::initializer_list<int> arg) {
        hval ans;
        assert(arg.size() % 2 == 0);
        for (auto it = arg.begin(); it != arg.end(); ) {
            int l = *it++, r = *it++;
            ans = ans + get(l, r);
        }
        return ans;
    }
}strhash;

void solve() {
    int n;
    std::string s;
    std::cin >> n >> s;
    strhash.init(2000005);

    StrHash sh1, sh2;
    sh1.build(s.begin(), s.end());
    sh2.build(s.rbegin(), s.rend());

    for (int i = 0; i < n; i++) {
        if (sh1.get({0,i,i+n,2*n}) == sh2.get(n-i,2*n-i)) {
            std::string t = s.substr(i,n);
            std::reverse(t.begin(), t.end());
            std::cout << t << "\n" << i;
            return;
        }
    }
    std::cout << -1;
}

int main() {
    std::cin.tie(0)->sync_with_stdio(0);
    int t = 1;
    while (t--) solve();
    return 0;
}

posted on 2024-03-08 12:19  chenfy27  阅读(28)  评论(0)    收藏  举报