1 条题解
-
0
自动搬运
来自洛谷,原作者为

sunkuangzheng
**搬运于
2025-08-24 23:09:57,当前版本为作者最后更新于2025-02-14 18:25:42,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
观察:在 中任意一个长度大于等于 的回文串都可以向两侧无限延伸。
证明:设 是回文串,记 ,此时应有 。因此 也是回文串,以此类推即可。
考虑对 求出每个中心的回文半径,如果回文半径大于等于 ,那么这个回文串就可以无限延伸,贡献容易计算;否则这个回文中心在所有位置的贡献都是一样的(特判边界情况),贡献也不难计算。
时间复杂度线性。
/** * author: sunkuangzheng * created: 01.09.2024 16:17:57 **/ #include<bits/stdc++.h> #ifdef DEBUG_LOCAL #include <mydebug/debug.h> #endif using ll = long long; const int N = 5e5+5,mod = 998244353; using namespace std; int T,n,m; string s; vector<int> manachar(string t){ string s; s = ".#"; for(char c : t) s += c,s += '#'; int n = s.size(),r = 0,mid = 0; vector<int> p(n); for(int i = 1;i < n;i ++){ if(i <= r) p[i] = min(r - i + 1,p[2 * mid - i]); while(s[i - p[i]] == s[i + p[i]]) p[i] ++; if(i + p[i] - 1 > r) r = i + p[i] - 1,mid = i; }for(int &i : p) i = i / 2; return p; }void los(){ cin >> n >> m >> s; ll ans = 0; auto p = manachar(s + s + s); s = " " + s; p.erase(p.begin()); for(int k = 2 * n;;k ++){ int i = (k + 1) / 2 - n,j = k / 2 + 1 - n; if(j > n) break; if(p[k] >= n + (i == j)){ int l = m / 2; ans = (ans + 1ll * l * (l - 1) % mod * n % mod + 1ll * (i + n - j + 1) * l) % mod; if(m & 1) ans = (ans + min(i,n - j + 1) + 1ll * l * n) % mod; }else ans = (ans + 1ll * p[k] * (m - 2) + min(i,p[k]) + min(n - j + 1,p[k])) % mod; }cout << ans << "\n"; }int main(){ ios::sync_with_stdio(0),cin.tie(0); for(cin >> T;T --;) los(); }
- 1
信息
- ID
- 11416
- 时间
- 1500ms
- 内存
- 512MiB
- 难度
- 5
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者