51nod 1092 回文字符串 (dp)
http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1092
这个题是poj-3280的简化版,这里只可以增加字符,设 dp[i][j] 为把以i开头j结尾的子串变为回文串的最少次数,
if(s[i]==s[j]) dp[i][j]=dp[i+1][j-1];
else dp[i][j]=min(dp[i+1][j],dp[i][j-1])+1;
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <vector> 5 #include <cstring> 6 #include <string> 7 #include <algorithm> 8 #include <string> 9 #include <set> 10 #include <functional> 11 #include <numeric> 12 #include <sstream> 13 #include <stack> 14 #include <map> 15 #include <queue> 16 #pragma comment(linker, "/STACK:102400000,102400000") 17 #define CL(arr, val) memset(arr, val, sizeof(arr)) 18 19 #define ll long long 20 #define inf 0x7f7f7f7f 21 #define lc l,m,rt<<1 22 #define rc m + 1,r,rt<<1|1 23 #define pi acos(-1.0) 24 25 #define L(x) (x) << 1 26 #define R(x) (x) << 1 | 1 27 #define MID(l, r) (l + r) >> 1 28 #define Min(x, y) (x) < (y) ? (x) : (y) 29 #define Max(x, y) (x) < (y) ? (y) : (x) 30 #define E(x) (1 << (x)) 31 #define iabs(x) (x) < 0 ? -(x) : (x) 32 #define OUT(x) printf("%I64d\n", x) 33 #define lowbit(x) (x)&(-x) 34 #define Read() freopen("a.txt", "r", stdin) 35 #define Write() freopen("b.txt", "w", stdout); 36 #define maxn 1000000000 37 #define N 1010 38 #define mod 1000000000 39 using namespace std; 40 41 int dp[N][N]; 42 char s[N]; 43 44 int main() 45 { 46 //Read(); 47 scanf("%s",s); 48 int m=strlen(s); 49 memset(dp,0,sizeof(dp)); 50 for(int i=m-1;i>=0;i--) 51 { 52 for(int j=i+1;j<m;j++) 53 { 54 if(s[i]==s[j]) dp[i][j]=dp[i+1][j-1]; 55 else dp[i][j]=min(dp[i+1][j],dp[i][j-1])+1; 56 //printf("%d\n",dp[i][j]); 57 } 58 } 59 printf("%d\n",dp[0][m-1]); 60 return 0; 61 }
还可以转化为最长公共子序列的问题求解,求最少变成回文串的操作次数,就是求有几个字符与对应的字符不一样,那么只要我把原字符翻转,然后求最长公共子序列,
用字符串长度减去公共子序列长度即可求解。
因为dp[i+1]计算时只用到了dp[i],dp[i+1],所以可以结合奇偶性用滚动数组优化空间。
1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <vector> 5 #include <cstring> 6 #include <string> 7 #include <algorithm> 8 #include <string> 9 #include <set> 10 #include <functional> 11 #include <numeric> 12 #include <sstream> 13 #include <stack> 14 #include <map> 15 #include <queue> 16 #pragma comment(linker, "/STACK:102400000,102400000") 17 #define CL(arr, val) memset(arr, val, sizeof(arr)) 18 19 #define ll long long 20 #define inf 0x7f7f7f7f 21 #define lc l,m,rt<<1 22 #define rc m + 1,r,rt<<1|1 23 #define pi acos(-1.0) 24 25 #define L(x) (x) << 1 26 #define R(x) (x) << 1 | 1 27 #define MID(l, r) (l + r) >> 1 28 #define Min(x, y) (x) < (y) ? (x) : (y) 29 #define Max(x, y) (x) < (y) ? (y) : (x) 30 #define E(x) (1 << (x)) 31 #define iabs(x) (x) < 0 ? -(x) : (x) 32 #define OUT(x) printf("%I64d\n", x) 33 #define lowbit(x) (x)&(-x) 34 #define Read() freopen("a.txt", "r", stdin) 35 #define Write() freopen("b.txt", "w", stdout); 36 #define maxn 1000000000 37 #define N 1010 38 #define mod 1000000000 39 using namespace std; 40 41 int dp[2][N]; 42 char s[N],ss[N]; 43 44 int main() 45 { 46 //Read(); 47 scanf("%s",s); 48 int m=strlen(s); 49 for(int i=0;i<m;i++) 50 ss[i]=s[m-i-1]; 51 ss[m]='\0'; 52 memset(dp,0,sizeof(dp)); 53 for(int i=0;i<m;i++) 54 { 55 for(int j=0;j<m;j++) 56 { 57 if(s[i]==ss[j]) dp[(i+1) & 1][j+1]=dp[i & 1][j]+1; 58 else dp[(i+1) & 1][j+1]=max(dp[i & 1][j+1],dp[(i+1) & 1][j]); 59 //printf("%d\n",dp[i+1][j+1]); 60 } 61 } 62 // printf("%d\n",dp[m][m]); 63 printf("%d\n",m-dp[m&1][m]); 64 return 0; 65 }