kattis传送门
vj传送门
对于
s
s
s串而言,考虑设
d
p
[
i
]
[
j
]
[
k
]
dp[i][j][k]
dp[i][j][k]表示所有长度为
l
e
n
=
j
−
i
+
1
+
k
len=j-i+1+k
len=j−i+1+k的包含
s
[
i
∼
j
]
s[i\sim j]
s[i∼j]的子串为子序列的回文串的个数,其也等价于在
s
[
i
∼
j
]
s[i\sim j]
s[i∼j]的基础上再添加
k
k
k个任意字符串使得字符串成为一个回文串的方案数,注意保证这些回文串两两不同,那么
d
p
[
1
]
[
n
]
[
n
]
dp[1][n][n]
dp[1][n][n]即为答案。假设串
s
[
i
∼
j
]
=
X
.
.
.
Y
,
X
≠
Y
s[i\sim j]=X...Y,X\ne Y
s[i∼j]=X...Y,X=Y,那么考虑这些符合条件的回文串的特点,首先该回文串的两端的字符可以是
26
26
26个字母中的任意一个,不过有两个字母比较特殊,那就是
X
X
X和
Y
Y
Y,先考虑字母
A
,
A
≠
X
,
A
≠
Y
A,A\ne X,A\ne Y
A,A=X,A=Y,我们把
A
A
A字母填充到这个长为
l
e
n
len
len的回文串两端。如下图所示:
由于我们要求
s
[
i
∼
j
]
s[i\sim j]
s[i∼j]必须被包含在上图所示的回文串中,而目前位置1和位置
l
e
n
len
len都被一个既不是
X
X
X又不是
Y
Y
Y的字母所占据,因此我们只能要求回文串的
2
∼
l
e
n
−
1
2\sim len-1
2∼len−1位置中包含
s
[
i
∼
j
]
s[i\sim j]
s[i∼j],首先可以肯定上图回文串的
2
∼
l
e
n
−
1
2\sim len-1
2∼len−1部分肯定也是一个回文串,于是我们要求出一个长度为
l
e
n
−
2
len-2
len−2的包含
s
[
i
∼
j
]
s[i\sim j]
s[i∼j]作为子序列的回文串的个数,它等于
d
p
[
i
]
[
j
]
[
k
−
2
]
dp[i][j][k-2]
dp[i][j][k−2]。
不过当
A
=
X
A=X
A=X的时候,如下图所示:
由于是左边的
X
X
X已经与
s
[
i
]
s[i]
s[i]相同,因此我们可以发现只要求上图回文串的
2
∼
l
e
n
−
1
2\sim len-1
2∼len−1位置包含
s
[
i
+
1
∼
j
]
s[i+1\sim j]
s[i+1∼j]作为子序列即可,注意这个条件是个充要条件。如果你要问为什么不可以包含
s
[
i
∼
j
]
s[i\sim j]
s[i∼j]作为子序列,其实只要稍加思考可以发现
s
[
i
+
1
∼
j
]
s[i+1\sim j]
s[i+1∼j]本身就是
s
[
i
∼
j
]
s[i\sim j]
s[i∼j]的子序列,我们求出包含
s
[
i
+
1
∼
j
]
s[i+1\sim j]
s[i+1∼j]作为子序列的回文串,自然也会包含所有可能的以
s
[
i
∼
j
]
s[i\sim j]
s[i∼j]作为子序列的回文串。不过你不能让条件变为包含
s
[
i
+
2
∼
j
]
s[i+2\sim j]
s[i+2∼j]作为子序列,这样显然是不能通过一个
X
X
X转移到
s
[
i
∼
j
]
s[i\sim j]
s[i∼j]的。
那么回文串 2 ∼ l e n − 1 2\sim len-1 2∼len−1包含 s [ i + 1 ∼ j ] s[i+1\sim j] s[i+1∼j]作为子序列的方案数其实就是 d p [ i + 1 ] [ j ] [ k − 1 ] dp[i+1][j][k-1] dp[i+1][j][k−1]。
如果将 X X X换成 Y Y Y也是同样地道理。
于是我们可以将这些状态加起来,得到 d p [ i ] [ j ] [ k ] = d p [ i + 1 ] [ j ] [ k − 1 ] + d p [ i ] [ j − 1 ] [ k − 1 ] + 24 d p [ i ] [ j ] [ k − 2 ] dp[i][j][k]=dp[i+1][j][k-1]+dp[i][j-1][k-1]+24dp[i][j][k-2] dp[i][j][k]=dp[i+1][j][k−1]+dp[i][j−1][k−1]+24dp[i][j][k−2]。
对于 s [ i ∼ j ] = X . . . X s[i\sim j]=X...X s[i∼j]=X...X的情况其实也就不难推了,跟上面相同,分类讨论一下即可,这里只有两种情况,要么最两端字母不为 X X X,有25种情况,要么最两端字母为 X X X,这种情况单独考虑,于是总方程为 d p [ i ] [ j ] [ k ] = d p [ i + 1 ] [ j − 1 ] [ k ] + 25 d p [ i ] [ j ] [ k − 2 ] dp[i][j][k]=dp[i+1][j-1][k]+25dp[i][j][k-2] dp[i][j][k]=dp[i+1][j−1][k]+25dp[i][j][k−2]。
不过还有一些边界条件需要处理。
当
k
<
0
k<0
k<0时,这时候意味着没办法添加字符,这时候方案数一定为0。
当 i > j i>j i>j时,这时候我们只需要添加 k k k个任意字符就是所有的方案数,由于是回文串,只需要决定前 ⌈ k 2 ⌉ \lceil \frac k2\rceil ⌈2k⌉个字符就可以决定整个回文串,因此方案数为 2 ⌈ k 2 ⌉ 2^{\lceil \frac k2\rceil} 2⌈2k⌉。
当 i = j i=j i=j时,这时候我们可不能当成 s [ i ∼ j ] = X . . . X s[i\sim j]=X...X s[i∼j]=X...X的这种情况处理,因为在这种情况下你在回文串两端添加一个 X X X就能成功契合 s [ i ∼ j ] s[i\sim j] s[i∼j]两端的 X X X,但 i = j i=j i=j时其实只有一个 X X X,所以需要特判。这里直接容斥即可,由于回文串长度为 k + 1 k+1 k+1,如果无限制的话总方案数为 2 6 ⌈ k + 1 2 ⌉ 26^{\lceil \frac {k+1}2\rceil} 26⌈2k+1⌉,然后除去其中不包含 s [ i ] s[i] s[i]的回文串,这些回文串有 2 5 ⌈ k + 1 2 ⌉ 25^{\lceil \frac {k+1}2\rceil} 25⌈2k+1⌉个,剩下的就是包含至少一个 s [ i ] s[i] s[i]的回文串。
这里给出一份参考代码:
int dp[maxn][maxn][maxn];
char s[maxn];
inline int dfs(int i,int j,int k){
if(k<0)return 0;
if(~dp[i][j][k])return dp[i][j][k];
register int &ans=dp[i][j][k];
if(i>j)ans=qpow(26,k+1>>1,mod);
else if(i==j)ans=sub(qpow(26,k+2>>1,mod),qpow(25,k+2>>1,mod));
else if(s[i]==s[j])ans=sum(dfs(i+1,j-1,k),25ll*dfs(i,j,k-2)%mod);
else ans=sum(sum(dfs(i+1,j,k-1),dfs(i,j-1,k-1)),24ll*dfs(i,j,k-2)%mod);
return ans;
}
int main(){
int n=rd();
if(!n)return wrn(1),0;
rds(s+1);
FOR(i,0,n+2)
FOR(j,0,n+2)
FOR(k,0,n+1)dp[i][j][k]=-1;
wrn(dfs(1,n,n));
}