/*要求输出最多添加几个字符可以使当前字符串变成回文串
* 解法是用当前字符串长度减去它和它的反串的LCS
*题目其实实在卡内存,但是可以把dp数组写成short
*这样也可以勉强过
*后来又试着写了滚动数组优化
*因为由状态转移方程可知
*dp[i][j]之和dp[i-1][j], dp[i-1][j-1], dp[i][j-1]有关
*所以可以对i或j进行滚动优化
*实现了从49308kb到172kb的优化
* 解法是用当前字符串长度减去它和它的反串的LCS
*题目其实实在卡内存,但是可以把dp数组写成short
*这样也可以勉强过
*后来又试着写了滚动数组优化
*因为由状态转移方程可知
*dp[i][j]之和dp[i-1][j], dp[i-1][j-1], dp[i][j-1]有关
*所以可以对i或j进行滚动优化
*实现了从49308kb到172kb的优化
*/
优化代码在上
未优化代码在下:
//滚动数组优化:
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 5010
using namespace std;
short dp[3][MAXN];
char str1[MAXN], str2[MAXN];
int lcs(char str1[], char str2[]) {
int len1 = strlen(str1);
int len2 = strlen(str2);
memset(dp, 0, sizeof(dp));
for(int i=0; i<len1; ++i) {
for(int j=0; j<len2; ++j) {
if(str1[i] == str2[j]) {
dp[i&1][j+1] = dp[1-(i&1)][j]+1;
} else dp[i&1][j+1] = max(dp[i&1][j], dp[1-(i&1)][j+1]);
}
}
return max(dp[0][len2], dp[1][len2]);
}
int main(void) {
int n;
while(scanf("%d", &n) != EOF) {
scanf("%s", str1);
strcpy(str2, str1);
reverse(str2, str2+n);
printf("%d\n", n-lcs(str1, str2));
}
return 0;
}
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 5010
using namespace std;
short dp[MAXN][MAXN];
char str1[MAXN], str2[MAXN];
int lcs(char str1[], char str2[]) {
int len1 = strlen(str1);
int len2 = strlen(str2);
memset(dp, 0, sizeof(dp));
for(int i=0; i<len1; ++i) {
for(int j=0; j<len2; ++j) {
if(str1[i] == str2[j]) {
dp[i+1][j+1] = dp[i][j]+1;
} else dp[i+1][j+1] = max(dp[i+1][j], dp[i][j+1]);
}
}
return dp[len1][len2];
}
int main(void) {
int n;
while(scanf("%d", &n) != EOF) {
scanf("%s", str1);
strcpy(str2, str1);
reverse(str2, str2+n);
printf("%d\n", n-lcs(str1, str2));
}
return 0;
}