题目大意:
只有一个测例,给定一个字符串并告诉其长度N(3 ≤ N ≤ 5,000),让你求最少插入多少个字符能使其成为回文字符串。
注释代码:
/*
* Problem ID : POJ 1159 Palindrome
* Author : Lirx.t.Una
* Language : GCC
* Run Time : 1094 ms
* Run Memory : 564 KB
*/
#pragma GCC optimize("O2")
#include <string.h>
#include <stdio.h>
//字符串的最大长度
#define MAXSTRLEN 5001
#define MAX(x,y) ( (x) > (y) ? (x) : (y) )
char s[MAXSTRLEN];//string
char r[MAXSTRLEN];//reverse string,反转字符串
//公共长度范围为[0, 5000]处于short范围内
//dp[i + 1][j + 1]只和dp[i][j + 1]、dp[i + 1][j]、dp[i][j]有关
//设a = i,b = i + 1,则
//dp[b][j + 1]只和dp[a][j + 1]、dp[b][j]、dp[a][j]有关
//由于dp[a][j + 1]和dp[a][j]来自a数组而dp[b][j]来自于b数组,且位于dp[b][j]之前
//因此就用a、b两个数组就可以搞定了
short dp[2][MAXSTRLEN];
int
main() {
int n;//字符串长度
int i, j;//技术变量
scanf("%d%s", &n, s);
strcpy(r, s);
strrev(r);//反转,只在GCC中有效,否则就只能用C++对string重载的strrev了
for ( i = 0; i < n; i++ )
for ( j = 0; j < n; j++ )
if ( s[i] == r[j] )
dp[( i + 1 ) % 2][j + 1] = dp[i % 2][j] + 1;
else
dp[( i + 1 ) % 2][j + 1] = MAX( dp[i % 2][j + 1], dp[( i + 1 ) % 2][j] );
//回文需要补全的字符个数即为原长减去原串和反串的最长公共子序列的长度
printf("%d\n", n - dp[n % 2][n]);
return 0;
}
无注释代码:
#pragma GCC optimize("O2")
#include <string.h>
#include <stdio.h>
#define MAXSTRLEN 5001
#define MAX(x,y) ( (x) > (y) ? (x) : (y) )
char s[MAXSTRLEN];
char r[MAXSTRLEN];
short dp[2][MAXSTRLEN];
int
main() {
int n;
int i, j;
scanf("%d%s", &n, s);
strcpy(r, s);
strrev(r);
for ( i = 0; i < n; i++ )
for ( j = 0; j < n; j++ )
if ( s[i] == r[j] )
dp[( i + 1 ) % 2][j + 1] = dp[i % 2][j] + 1;
else
dp[( i + 1 ) % 2][j + 1] = MAX( dp[i % 2][j + 1], dp[( i + 1 ) % 2][j] );
printf("%d\n", n - dp[n % 2][n]);
return 0;
}
单词解释:
palindrome:n, 回文
symmetrical:n, 对称的
identically:adv, 相同地