以下事实是显而易见的,但在解决此问题时非常重要。
- 长度的回文 N N N 由其第一个唯一确定 ⌈ N 2 ⌉ \lceil \frac{N}{2} \rceil ⌈2N⌉ 字符。
现在我们将通过示例来解释解决方案。
首先,我们考虑
S
=
S=
S=ABCDE
. 显然,如果前三个字符在字典顺序上小于或等于,则 ABB
5
5
5-由他们确定的字符回文在字典上小于
S
S
S .相反,如果前三个字符在字典顺序上大于或等于,则 ABD
5
5
5-由他们确定的字符回文在字典上大于
S
S
S.
问题是,如果第一个
3
3
3 回文字符是,即如果是?对于此字符串,比较第一个 ABCABCBA
3
3
3 字符不足以确定回文是否在字典上小于
S
S
S,所以我们必须实际将此字符串与
S
S
S.这一次,此字符串在字典顺序上小于或等于
S
S
S,所以它满足条件。我们必须计算的是回文的数量,其第一个
3
3
3 字符为…等等。这些可以以与计算基数整数相同的方式进行计数 AAAAABABBABC
26
26
26(因为每个字符串都可以解释为基数的整数
26
26
26 通过查看 A
=
0
=0
=0, B
=
1
=1
=1,…,和Z
=
25
=25
=25.
接下来,让我们考虑一下案例
S
=
S=
S=DCBA
. 这一次,我们可以做几乎相同的讨论。唯一的“问题”是当前两个字符的回文时,即.这一次,此字符串在字典顺序上大于 DCDC CD
S
S
S,因此它不满足条件。
无论如何,可以通过确定以下两个问题来解决问题:
-
有多少回文在字典上比“问题”回文(即,回文,其第一个 ⌈ N 2 ⌉ \lceil \frac{N}{2} \rceil ⌈2N⌉ 字符等于 S S S)?
-
“问题”回文是否满足条件?
请注意,根据实现的不同,通过以下方式解决它可能更容易:
- 计算在字典上小于或等于“问题”回文的回文数量
- 将计数递减 1 1 1 如果“问题”回文不满足条件
在示例代码中,使用了此方法。
示例代码 (C++):
#include<bits/stdc++.h>
#define mod 998244353
using namespace std;
int main(){
int tc;
cin >> tc;
while(tc>0){
tc--;
int n;
string s;
cin >> n >> s;
long long cres=0;
string target=s;
int p=0,q=n-1;
while(p<q){
target[q]=target[p];
p++;q--;
}
int last=(n-1)/2;
for(int i=0;i<=last;i++){
cres*=26;cres%=mod;
cres+=(s[i]-'A');cres%=mod;
}
cres++;cres%=mod;
if(s<target){cres+=(mod-1);cres%=mod;}
cout << cres << '\n';
}
return 0;
}