#include<bits/stdc++.h> #define all(vec) vec.begin(), vec.end() #define PB push_back #define PF push_front #define EB emplace_back #define EF emplace_front #define EM emplace #define FI first #define SE second #define pct __builtin_popcountll #define ctz __builtin_ctzll #define SZ(a) ((long long) a.size()) #define FOR(i, a, b) for (int i = (a); i <= (b); ++i) #define ROF(i, a, b) for (int i = (a); i >= (b); --i) #define debug(var) cerr << #var << ":" << var << "\n"; #define cend cerr << "\n-----------\n" #define fsp(x) fixed << setprecision(x)
usingnamespace std;
using ll = longlong; using ull = unsignedlonglong; using DB = double; using LD = longdouble; using CD = complex<double>; staticconstexpr ll MAXN = (ll) 1e6 + 10, INF = (1ll << 61) - 1; staticconstexpr ll mod = (ll) 1e9 + 7; staticconstexprdouble eps = 1e-8; constdouble pi = acos(-1.0);
ll lT;
structU { using u128 = __uint128_t; staticconstexpr ll MOD = (1ULL << 61) - 1;
ll v;
U() : v(0) { }
U(ll x) { ll t = x % MOD; if (t < 0) t += MOD; v = (ll) t; }
staticinline ll add(ll a, ll b){ ll s = a + b; if (s >= MOD) s -= MOD; return s; }
staticinline ll sub(ll a, ll b){ return (a >= b) ? (a - b) : (a + MOD - b); }
staticinline ll mul(ll a, ll b){ u128 t = (u128) a * b; ll s = ll(t & MOD) + ll(t >> 61); if (s >= MOD) s -= MOD; return s; }
U &operator+=(const U &o) { v = add(v, o.v); return *this; }
U &operator-=(const U &o) { v = sub(v, o.v); return *this; }
U &operator*=(const U &o) { v = mul(v, o.v); return *this; }
friend U operator+(U a, const U &b) { a += b; return a; }
friend U operator-(U a, const U &b) { a -= b; return a; }
friend U operator*(U a, const U &b) { a *= b; return a; }
friendbooloperator==(const U &a, const U &b) { return a.v == b.v; } friendbooloperator!=(const U &a, const U &b) { return a.v != b.v; } friendbooloperator<(const U &a, const U &b) { return a.v < b.v; } friendbooloperator>(const U &a, const U &b) { return a.v > b.v; } friendbooloperator<=(const U &a, const U &b) { return a.v <= b.v; } friendbooloperator>=(const U &a, const U &b) { return a.v >= b.v; } };
const U base = 131;
// AC https://vjudge.net/solution/65151535 string matching 测试了find函数功能 // 2025/11/4 // AC https://www.luogu.com.cn/record/245201000 测试了这个push,pop,以及增强get鲁棒性。 // 2026/3/21 改为了 0-based structHS { vector<U> hs, powBase; U hashval; ll n; string s;
HS(const string &ls) { n = SZ(ls); s = ls; hs.assign(n, 0); powBase.assign(n + 1, 0); powBase[0] = 1; for (ll i = 1; i <= n; ++i) { powBase[i] = powBase[i - 1] * base; } if (n > 0) { hs[0] = U(s[0]); for (ll i = 1; i < n; ++i) { hs[i] = hs[i - 1] * base + U(s[i]); } hashval = hs[n - 1]; } else { hashval = 0; } }
U get(ll l, ll r){ if (n == 0) return0; l = max(0ll, l); r = min(n - 1, r); if (l > r) return0; if (l == 0) return hs[r]; return hs[r] - hs[l - 1] * powBase[r - l + 1]; }
U get(ll l){ returnget(l, n - 1); }
ll find(const string &ls){ U hxfind = 0; ll m = SZ(ls); if (m == 0) return n + 1; if (m > n) return0; for (ll i = 0; i < m; ++i) { hxfind = hxfind * base + ls[i]; } ll res = 0; for (ll r = m - 1; r < n; ++r) { U hx = get(r - m + 1, r); if (hx == hxfind) { res++; } } return res; }