专栏文章
「TPOI-1C」Standard Problem. Solution
P11749题解参与者 3已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @miq9advr
- 此快照首次捕获于
- 2025/12/04 01:03 3 个月前
- 此快照最后确认于
- 2025/12/04 01:03 3 个月前
观察:在 中任意一个长度大于等于 的回文串都可以向两侧无限延伸。证明:设 是回文串,记 ,此时应有 。因此 也是回文串,以此类推即可。
考虑对 求出每个中心的回文半径,如果回文半径大于等于 ,那么这个回文串就可以无限延伸,贡献容易计算;否则这个回文中心在所有位置的贡献都是一样的(特判边界情况),贡献也不难计算。
时间复杂度线性。
CPP/**
* 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();
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...