题目链接:传送门
题目大意:略
题目思路:DP
先预处理,分别以每个字母为中心处理能形成的回文串,再以两个字母为中心处理能形成的回文串。
然后 dp[i] 表示1~i 能形成的数目最少的回文串。
转移方程:if(vis[j][i]==1&&dp[i]>dp[j]+1)dp[i]=dp[j]+1;
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstring> #include <stack> #include <cctype> #include <queue> #include <string> #include <vector> #include <set> #include <map> #include <climits> #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define fi first #define se second #define ping(x,y) ((x-y)*(x-y)) #define mst(x,y) memset(x,y,sizeof(x)) #define mcp(x,y) memcpy(x,y,sizeof(y)) using namespace std; #define gamma 0.5772156649015328606065120 #define MOD 1000000007 #define inf 0x3f3f3f3f #define N 200005 #define maxn 10005 typedef pair<int,int> PII; typedef long long LL; int n,m,k,T,ans,cnt; char str[3111]; bool vis[3001][3001]; int d[3001]; int main(){ int i,j,group,x,y; scanf("%s",str); n=strlen(str); for(i=0;i<n;++i)for(j=0;i-j>=0&&i+j<n;++j) if(str[i-j]==str[i+j])vis[i-j][i+j]=1; else break; for(i=0;i<n;++i)for(j=1;i-j>=0&&i+j-1<n;++j) if(str[i-j]==str[i+j-1])vis[i-j][i+j-1]=1; else break; for(i=0;i<n;++i){ if(vis[0][i]){d[i]=1;continue;} d[i]=inf; for(j=0;j<i;++j)if(vis[j+1][i]&&d[i]>d[j]+1)d[i]=d[j]+1; } printf("%d ",d[n-1]); return 0; }