题意:给一个字符串,求回文子序列个数,最后答案模10007
区间dp简单题
区间dp一般第一层枚举区间长度,第二层就是枚举区间了,第三层可能还有什么枚举短点,一般是n^3的复杂度,如果满足一定的条件可以用四边形不等式优化。
这道题就二层循环就可以了。
区间的遍历顺序,也有很多种写法,但不过写的前提就是,要确定递推中以前的状态都是存在的
dp[j][i]=dp[j+1][i]+dp[j][i-1]-dp[j+1][i-1];表示j到i的回文数,等于j到i-1,和j+1到i,然后在容斥掉j+1到i-1的。
if(s[i]==s[j])
dp[j][i]=dp[j][i]+dp[j+1][i-1]+1如果i和j想等,就要加上j+1到i-1的,然后j和i也可以构成
#include<bits/stdc++.h>
using namespace std;
#define cppiofast ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int inf=0x3f3f3f3f;
const int N=2010;
const int mod=10007;
char s[1010];
int dp[1010][1010];
int main()
{
cppiofast;
int T,kase=1;
cin>>T;
while(T--)
{
cin>>s;
memset(dp,0,sizeof(dp));
int len=strlen(s);
for(int i=0;i<len;i++)
dp[i][i]=1;
for(int i=1;i<len;i++)
{
for(int j=i-1;j>=0;j--)
{
dp[j][i]=(dp[j+1][i]+dp[j][i-1]-dp[j+1][i-1]+mod)%mod;
if(s[i]==s[j])
dp[j][i]=(dp[j][i]+dp[j+1][i-1]+1)%mod;
}
}
cout<<"Case "<<kase++<<": ";
cout<<dp[0][len-1]<<endl;
}
return 0;
}