题目描述
题解
看到题感觉毫无头绪啊。。这怎么搞。
让我困惑的是:它不是像中序遍历一样,每个点只在序列里出现了一次,而是每一次走到都要算一次。
但是这是一棵树结构,那么一棵树最关键的是什么?根!
根又有什么性质?不难发现,如果一段序列可以代表一颗子树的话,子树的根一定是这个序列的第一个和最后一个!
——这也许就是这道题的突破口了。
f(i,j)表示i~j这一段序列代表子树的形态数,这里s(l)=s(r)并且r-l+1>=3
一遍记搜。。。
代码
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define N 305
#define Mod 1000000000
#define LL long long
int n;
char s[N];
LL ans,f[N][N];
LL dp(int l,int r)
{
if (l>r) return 0;
if (f[l][r]!=-1) return f[l][r];
if (s[l]!=s[r]||r-l+1<=2)
{
f[l][r]=0;
return f[l][r];
}
f[l][r]=0;
for (int i=l;i<r;++i)
if (s[i]==s[l])
f[l][r]=(f[l][r]+dp(l,i)*dp(i+1,r-1)%Mod)%Mod;
return f[l][r];
}
int main()
{
gets(s);n=strlen(s);
for (int i=n;i>=1;--i) s[i]=s[i-1];
memset(f,-1,sizeof(f));
for (int i=1;i<=n;++i) f[i][i]=1;
ans=dp(1,n);
printf("%lld\n",ans);
}