51NOD 1154 回文串的划分(DP)
思路:参考了网上,思路很清奇,借助vis[i][j]来表示从i到j是否为回文串,回文串这边是用的双重循环来写的;dp[i]用来表示以i结尾的字符串最少的回文串有多长。
#include<cstring> #include<iostream> #include<algorithm> using namespace std; const int maxn = 5e3 + 10; int dp[maxn];//dp[i]表示的是以第i个字符结尾的最少划分数 //dp[i] = min(dp[i],dp[j]+1) 当j到i是回文串时 char s[maxn]; bool vis[maxn][maxn];//vis[i][j]表示i到j的字符串是否是回文串 int main(){ gets(s); int len = strlen(s); memset(vis, 0, sizeof vis); for (int i = 0; i < len; i++) vis[i][i] = 1; dp[0] = 1; for (int i = 1; i < len; i++){ dp[i] = i; dp[i] = min(dp[i], dp[i - 1] + 1); for (int j = i - 1; j >= 0; j--){ if (j == i - 1 && s[i] == s[j]){ if (j - 1 >= 0)dp[i] = min(dp[i], dp[j - 1] + 1); else dp[i] = 1; vis[j][i] = 1; } else if (vis[j + 1][i - 1] && s[i] == s[j]){ if (j - 1 >= 0)dp[i] = min(dp[i], dp[j - 1] + 1); else dp[i] = 1; vis[j][i] = 1; } } } cout << dp[len - 1] << endl; return 0; }