传送门
题意:
给一个字符串,问其中每一个回文子串的总价值。
回文子串的价值,定义:
1、如果是回文的则价值为1;
2、如果左半个回文部分的价值为k-1,则当前子串的价值为k。
思路:
1、dp[i][j]表示从第i个字符到第j个字符的子串价值,num[i]表示价值为i的子串的个数;
2、先枚举长度1、2的价值,再通过dp[i+1][j-1]尝试更新dp[i][j]的值;
3、由于子串的值可以累加,则还需对num[i]进行处理。
#include <bits/stdc++.h> using namespace std; #define N 5005 int dp[N][N]; char s[N]; int num[N]; int main() { scanf("%s",s); int n = strlen(s); for(int i=0;i<n;i++){ dp[i][i] = 1; } num[1] = n; for(int i=1;i<n;i++){ if(s[i]==s[i-1]) num[2]++,dp[i-1][i] = 2; //在单独枚举长度为2 } for(int i=2;i<n;i++){ for(int j=0;j+i<n;j++){ if(!dp[j+1][j+i-1]) continue; //如果不枚举长度2 则当 i==1 时 dp[j+1][j+1-1] 为 dp[j+1][j] if(s[j]!=s[j+i]) continue; dp[j][j+i] = dp[j][j+(i+1)/2-1] + 1; num[dp[j][j+i]]++; } }j for(int i=n;i>=1;i--){ num[i-1] += num[i]; } for(int i=1;i<=n;i++){ printf(i==1?"%d":" %d",num[i]); } return 0; }