这题是给你一个字符串要你统计其中出现过多少个不同的回文子串,回文子串不一定每个字符都连续,不同是说位置不同如aba的答案就是5 因为不同的回文子串有a(第一个a), b,aa(因为子串的字符可以不连续), aba,a(最后一个a)
************同样是找回文串的一题 建议看一下点击打开链接*******************
注意到任意一个回文子序列收尾两个字符一定是相同的,于是可以区间dp,用dp[i][j]表示原字符串中[i,j]位置中出现的回文子序列的个数,有递推关系:
当 第i个字符与第j个字符不相等时有dp[i][j]=dp[i+1][j]+dp[i][j-1]-dp[i+1][j-1]反之,i和j位置出现的字符相同,那么dp[i][j]=dp[i+1][j]+dp[i][j-1]+1,注意边界特判一下就可以了
dp式看不懂得可以用 ABA自己验证一下,细节见代码注释
#include <cstdio> #include <cstring> using namespace std; int dp[1010][1010],len; int const mod=10007; char ch[1010]; int memdp(int i,int j)//记忆化搜素 { if(i>j) return 0;//不合法的区间 if(i==j) return 1;//区间长度为一返回一就可以了 if(dp[i][j])return dp[i][j];//该区间已经算过了,就直接返回结果 if(ch[i]==ch[j]) return dp[i][j]=(memdp(i,j-1)+memdp(i+1,j)+1)%mod;//首尾的字符相同 return dp[i][j]=(memdp(i,j-1)+memdp(i+1,j)-memdp(i+1,j-1)+mod)%mod;//首尾的字符不同 //**** 需要注意这步中间结果可能为负值 所以要加上模的值 } int main() { int T,cas=0;scanf("%d",&T); while(++cas<=T) { scanf("%s",ch); memset(dp,0,sizeof(dp));//初始化dp数组 len=strlen(ch);//得到字符数组的长度 printf("Case %d: %d\n",cas,memdp(0,len-1)%mod); } return 0; }