这题一开始的思路是:枚举所有子集,判断各个子集是不是回文串。
但是很显然只能解决规模为10以下的
所以需要使用dp
对这类问题的感觉就是,新加的哪一个元素,对所有的前面的东西都有影响,所以称为最长上升子序列问题的类似题目
下面是AC代码:
//思路有两个 //第一个是枚举所有子集,判断哪些是回文串 //日狗,又他妈是枚举所有的子集 //当然还有另外一种方式 //d[i]表示前i 个字符的最大回文数 //d[i] = if(k~i 是回文串),那么d[i] = min(d[k - 1] + 1) k的范围是1~i #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn = 1000 + 10; char s[maxn]; int d[maxn]; int vis[maxn]; bool is_pali(int left,int right) { while(left < right) { if(s[left] != s[right]) return false; left++; right--; } return true; } int dp(int pos) { if(vis[pos]) return d[pos]; vis[pos] = 1; d[pos] = pos; for(int i = pos;i > 0;i--) { if(is_pali(i,pos)) { d[pos] = min(dp(i - 1) + 1,d[pos]); } } return d[pos]; } int main() { #ifdef local freopen("input.txt","r",stdin); freopen("out.txt","w",stdout); #endif int T; scanf("%d",&T); memset(s,0,sizeof(s)); for(int i = 0;i < T;i++) { memset(vis,0,sizeof(vis)); scanf("%s",s + 1); int len = strlen(s + 1); printf("%d\n",dp(len)); } return 0; }