LightOJ1033 Generating Palindromes(区间DP/LCS)

题目要计算一个字符串最少添加几个字符使其成为回文串。

一年多前,我LCS这道经典DP例题看得还一知半解时遇到一样的问题,http://acm.fafu.edu.cn/problem.php?id=1007

当时完全靠自己瞎YY出了LCS的解法:

我当时这么想的:

  • 把字符串分成两个部分,假设这两个部分分别就属于新的回文串的对称的两部分,那么要添加最少的字符串形成回文串就需要前一部分和后一部分公共部分最多,也就是它们的(一正一反)LCS。
  • 这样就是枚举中间部分的位置(另外还要分情况讨论奇数和偶数回文串,奇数的枚举的就是中间元素的位置),然后计算两个部分的长度-2*LCS(一正一反),取最小的。
  • 两个部分的长度的(一正一反)LCS可以通过计算原字符串和其反转串的LCS预处理出来,就是dp[i][j]的意义——s11...s1i和s21...s2j的LCS。

我搜了下,真有LCS的解法,不过不一样的是很简单就是长度-LCS就是解。真难想象当时能完全靠自己想出这个解法的我。。

现在做这题,只会用区间DP乱搞了,虽然状态转移只是靠着感觉去写,正确性一知半解。。

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 #define INF (1<<29)
 6 int d[222][222];
 7 char str[222];
 8 int main(){
 9     int t;
10     scanf("%d",&t);
11     for(int cse=1; cse<=t; ++cse){
12         scanf("%s",str);
13         int n=strlen(str);
14         for(int i=0; i<n; ++i){
15             for(int j=i+1; j<n; ++j) d[i][j]=INF;
16             for(int j=0; j<=i; ++j) d[i][i]=0;
17         }
18         for(int len=2; len<=n; ++len){
19             for(int i=0; i+len<=n; ++i){
20                 if(str[i]==str[i+len-1]) d[i][i+len-1]=d[i+1][i+len-2];
21                 else{
22                     for(int j=i; j<i+len-1; ++j) d[i][i+len-1]=min(d[i][i+len-1],d[i][j]+i+len-1-j);
23                     for(int j=i+len-1; j>i; --j) d[i][i+len-1]=min(d[i][i+len-1],d[j][i+len-1]+j-i);
24                 }
25             }
26         }
27         printf("Case %d: %d\n",cse,d[0][n-1]);
28     }
29     return 0;
30 }

 

转载于:https://www.cnblogs.com/WABoss/p/5128264.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值