传送门
设
f
[
l
]
[
r
]
f[l][r]
f[l][r]为
s
[
l
⋅
⋅
⋅
r
]
s[l···r]
s[l⋅⋅⋅r]的序列能构成的树的方案数,就可以考虑转移,首先
s
[
l
]
s[l]
s[l]必须等于
s
[
r
]
s[r]
s[r],然后我们可以让
s
[
l
]
s[l]
s[l]作为当前的根,用乘法原理枚举
k
k
k转移,那么
s
[
k
]
s[k]
s[k]一定要等于
s
[
r
]
s[r]
s[r],
如果
l
+
1
≤
k
≤
r
−
2
l+1\le k \le r-2
l+1≤k≤r−2,则
f
[
l
]
[
r
]
+
=
f
[
l
+
1
]
[
k
−
1
]
×
f
[
k
]
[
r
]
f[l][r]+=f[l+1][k-1]\times f[k][r]
f[l][r]+=f[l+1][k−1]×f[k][r],
如果
k
=
r
−
1
k=r-1
k=r−1,则
f
[
l
]
[
r
]
+
=
f
[
l
+
1
]
[
r
−
2
]
×
f
[
r
−
1
]
[
r
]
=
f
[
l
+
1
]
[
r
−
2
]
×
0
=
0
f[l][r]+=f[l+1][r-2]\times f[r-1][r]=f[l+1][r-2]\times 0=0
f[l][r]+=f[l+1][r−2]×f[r−1][r]=f[l+1][r−2]×0=0,
如果
k
=
r
k=r
k=r,则
f
[
l
]
[
r
]
+
=
f
[
l
+
1
]
[
r
−
1
]
×
f
[
r
]
[
r
]
=
f
[
l
+
1
]
[
r
−
1
]
×
1
=
f
[
l
+
1
]
[
r
−
1
]
.
f[l][r]+=f[l+1][r-1]\times f[r][r]=f[l+1][r-1]\times 1=f[l+1][r-1].
f[l][r]+=f[l+1][r−1]×f[r][r]=f[l+1][r−1]×1=f[l+1][r−1].
所以式子可以统一写成
f
[
l
]
[
r
]
+
=
∑
k
=
l
+
2
r
f
[
l
+
1
]
[
k
−
1
]
×
f
[
k
]
[
r
]
(
s
[
k
]
=
=
s
[
r
]
)
f[l][r]+=\sum_{k=l+2}^rf[l+1][k-1]\times f[k][r]\ (s[k]==s[r])
f[l][r]+=∑k=l+2rf[l+1][k−1]×f[k][r] (s[k]==s[r])
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define maxn 305
using namespace std;
int f[maxn][maxn],n;
const int mod=1e9;
char s[maxn];
int main(){
scanf("%s",s+1); n=strlen(s+1);
for(int i=1;i<=n;i++) f[i][i]=1;
for(int i=2;i<=n;i++)
for(int l=1;l<=n-i+1;l++){
int r=l+i-1;
if(s[l]!=s[r]) continue;
for(int k=l+2;k<=r;k++)
if(s[k]==s[r])
(f[l][r]+=1LL*f[l+1][k-1]*f[k][r]%mod)%=mod;
}
printf("%d\n",f[1][n]);
return 0;
}