给一个字符串, 要求把它分割成若干个子串,使得每个子串都是回文串。问最少可以分割成多少个。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int INF=0x3f3f3f3f;
char str[1010];
int dp[1010];
bool check(int l,int r)
{
for(int i=l,j=r;i<=j;i++,j--)
{
if(str[l]!=str[r])
{
return false;
}
return true;
}
}
int main()
{
int t;
cin>>t;
for(int i=1;i<=t;i++)
{
scanf("%s",str+1);//这个地方从1开始是为了后面的方便
int len=strlen(str+1);
for(int j=1;j<=len;j++)
{
dp[j]=INF;
}
dp[0]=0;
for(int ii=1;ii<=len;ii++)
{
for(int jj=ii;jj>=1;jj--)
{
if(check(jj,ii)==true)
{
dp[ii]=min(dp[jj-1]+1,dp[ii]);
}
}
}
printf("%d\n",dp[len]);
}
}
对于回文串的判断,也可以直接dp:
void pre()
{
/*令flag[i][j]=1表示长度为i从str的第j个位置开始有一回文串,
否则flag[i][j]=0*/
memset(flag,0,sizeof(flag));
for(int i=1;i<=l;i++)flag[1][i]=1;
if(l==1)return;
for(int i=1;i<=l-1;i++)if(str[i]==str[i+1])flag[2][i]=1;
for(int i=3;i<=l;i++)
for(int j=1;j<=l-i+1;j++)
{
/*j开始i的长度是回文词是加上从j+1开始i-2的长度
是回文词切加上两边构成新的回文词 */
if(flag[i-2][j+1] && str[j]==str[j+i-1])
flag[i][j]=1;
}
}