Description
简单的说就是定义一个回文串为 阶回文需要满足把他切成两半(, ,奇数长度中间的字符不用管)
然后这两半都是 阶的,定义回文串都可以是 阶。
Solution
不会双模数哈希,抄的题解,单模数一直被卡。
按照定义,显然是可以类似于 的思想去做的,定义所有朴素的回文串都为 阶,那么先找出所有的回文串,显然当前回文串 的阶数为左边的阶数,因此直接 统计所有答案即可。
由于有结论:本质不同回文串的数量级别为 ,所以通过 可以找到所有本质不同回文串并实现上述的赋值操作。需要用双模数哈希来判断是否本质不同,总体时间复杂度 。
Code
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int mod1 = 998244353, mod2 = 1e9 + 9; const int N = 5e5 + 5; map<ll, int> mp; int cal[N], p[N]; char s[N], str[N]; ll f1[N], f2[N], hs1[N], hs2[N]; void iniths(int n, ll hs[N], int b, int mod) { for (int i = 1; i <= n; i++) { hs[i] = (hs[i - 1] * b % mod + s[i] - 'a' + 1) % mod; } } int geths(int l, int r, ll hs[N], ll f[N], int mod) { return (hs[r] - hs[l - 1] * f[r - l + 1] % mod + mod) % mod; } ll __hash(int l, int r) { return geths(l, r, hs1, f1, mod1) * 123456ll + geths(l, r, hs2, f2, mod2); } void update(int l, int r) { if (l == r) { mp[__hash(l, r)] = 1; } else { mp[__hash(l, r)] = mp[__hash(l, (l + r - 1) / 2)] + 1; } } void manacher(int n) { str[1] = '$'; for (int i = 1; i <= n; i++) { str[i << 1] = s[i], str[i << 1 | 1] = '#'; } str[(n + 1) << 1] = '*'; int id = 0, mx = 0; for (int i = 1; i <= 2 * n + 1; i++) { if (i <= mx) { p[i] = min(mx - i, p[2 * id - i]); } else { p[i] = 1; } while (str[i + p[i]] == str[i - p[i]]) { p[i]++; int len = (p[i] + (i % 2 == 0)) / 2 - 1; if (len >= 0) { if (i & 1) { update(i / 2 - len, (i + 1) / 2 + len); } else { update(i / 2 - len, i / 2 + len); } } } if (i + p[i] > mx) { mx = i + p[i], id = i; } } } void solve() { int n, m; cin >> n >> m; cin >> (s + 1); mp.clear(); for (int i = 0; i <= n; i++) { cal[i] = 0; } iniths(n, hs1, 233, mod1); iniths(n, hs2, 31, mod2); manacher(n); for (auto &it : mp) { cal[it.second]++; } for (int i = n - 1; i >= 0; i--) { cal[i] += cal[i + 1]; cal[i] %= mod1; } ll ans = 0; int res = 2; for (int i = 1; i <= m; i++) { ans += 1LL * res * cal[i] % mod1; ans %= mod1; res = res * 2LL % mod1; } cout << ans << '\n'; } void prework() { f1[0] = f2[0] = 1; for (int i = 1; i <= N - 1; i++) { f1[i] = f1[i - 1] * 233 % mod1; f2[i] = f2[i - 1] * 31 % mod2; } } int main() { ios::sync_with_stdio(false), cin.tie(0); int T = 1; cin >> T; prework(); while (T--) { solve(); } return 0; } /* 10 0 1 0 0 0 1 0 0 0 1 */