poj 1159 Palindrome 动态规划

lstar@ubuntu:~/ds/poj$ ./a.out < 1159_2.in.dat 
2
lstar@ubuntu:~/ds/poj$ cat 1159_2.in.dat 
4
Ab3A


Ab33A这种对奇数的情况也需要特殊考虑,如果以中间的3为分界,则返回2,其实最小应该是1


3L7YWY 

最短匹配 3L7YWY7L3 只需要3个,且并不是以原中心点为7 Y W进行扩展的,所以自己推断的状态方程是不正确的。

记录错误状态方程如下:

以原始字符串中间拆成两个字串,求两个字串如何添加的字符,成为2个相等的字串。这种思考方式就是错误的。


最后只能参考前辈文章:

动态规划法。设字符串为S,长度为L,d[i][j]表示以第i个字符为首,第j个字符为尾的字符串构成回文最少需要添加的字符个数,i和j的初值分别为1、L。

如果S[i] == S[j],即字符串两端的字符相等,d[i][j] = d[i+1][j-1],

即d[i][j]等于去掉头尾后的字符串的d值。

如果S[i] != S[j],此时划分出两个子问题,求d[i][j-1]和d[i+1][j],它两中较小的值再加1即为d[i][j](加上的1个字符是用于和S[i]或者S[j]构成对称的)。

状态转移方程


http://blog.csdn.net/code_pang/article/details/8759600


#include <iostream>
#include <stdio.h>
#include <cstring>

using namespace std;

#define MAX_N (5000+1)
char Old[MAX_N];
unsigned short dp[MAX_N][MAX_N]; //dp[i][j]  是字符以i为首j为尾构成回文字符串的最小长度,i,j初始值为1,L

#define printf //
#define inf 200000000
int main()
{
	int n;
	while(cin>>n)
	{
		int minp = inf;
		for(int i=1;i<=n;i++)
			cin>>Old[i];

		//长度为0初始化i==j的情况
		for(int i=1;i<=n;i++)
		{
			dp[i][i]=0;
		}
		//长度为1,初始化i+1=j的情况
		for(int i=1;i<n;i++)
		{
			int j= i +1;
			if(Old[i] == Old[j])
				dp[i][j] =0;
			else
				dp[i][j] =1;
		}

		//长度为2到n-1的情况
		for(int k=2;k<n;k++)
		{
			for(int j=k+1;j<=n;j++)
			{
				int i=j-k;

				if( Old[i] == Old[j] )
					dp[i][j] = dp[i+1][j-1];
				else
					dp[i][j] = min(dp[i+1][j],dp[i][j-1])+1;
				
			}
		}

		minp = dp[1][n];
		

		cout<<minp<<endl;

	}
}

测试数据:
6
yvrqDQ
6
KOw5OF
6
fvHWds
6
RbKh3c
6
ATaOfA
6
9ycl9f
6
3aukVO
6
tqFlVf
6
6tZ8xT
6
XjW7no
6
iXXTpu
6
qj83Jl
6
X6FmjS
6
sw4W5R
6
2rtd7F
6
NnbkTF
6
D8h2iH
6
n6QzoR
6
EX3TNP
6
9N1Z6P
6
htI96k
6
IEgazA
6
ZUCPG1
6
QbuMHm
6
aslfkq
6
2fdECC
6
EXwVpZ
6
4hjtJT
6
gdrMvh
6
8cQixk
6
XdPkCU
6
DX4WyI
6
FlVW7N
6
zjO29H
6
UDfGym
6
oJJuRH
6
ZCwv6L
6
Vdt7q3
6
2TEmGW
6
ExJWoT
6
VIZvwB
6
ZJQTqV
6
k60AL8
6
P77mR5
6
kKWmd8
6
3b0yUI
6
TnQdal
6
cLZ4BM
6
JghswV
6
nD0Gz6
6
C4Bzhs
6
kcYUOP
6
8QzYaS
6
t1s0l2
6
o0vaqo
6
ye2yFB
6
dHqw66
6
hpeWYY
6
027F8u
6
DkivLX
6
kMRyNx
6
3W9oFw
6
dFckby
6
5iWypN
6
sFxYrj
6
xXx4CL
6
aZxa3L
6
HeoVfl
6
HiAiwA
6
dzTHlP
6
KKINpL
6
YoRLST
6
iglhFe
6
3UvOHd
6
EuIfbf
6
8nxVKO
6
pVJ11q
6
rw5SPe
6
OFcUgT
6
MMK2wt
6
B5mc9E
6
uulqzR
6
P5zgau
6
p3fJjF
6
6CEgwu
6
iB4BZK
6
egRG27
6
u7ETjZ
6
9wSSoA
6
qBx3UD
6
xbvEfP
6
32WqJU
6
xQYVPG
6
JqrWsQ
6
0kpLFo
6
wCxf70
6
2G5aAi
6
DW8Z6r
6
P79OyG
6
3L7YwY

结果

5
3
5
5
3
3
5
5
5
5
4
5
5
5
5
5
5
5
5
5
5
5
5
5
5
4
5
5
5
5
5
5
5
5
5
4
5
5
5
5
5
5
5
4
5
5
5
5
5
5
5
5
5
5
3
3
4
4
5
5
5
5
5
5
5
3
3
5
3
5
4
5
5
5
3
5
4
5
5
4
5
4
5
5
5
3
5
5
4
5
5
5
5
5
5
5
5
5
5
3



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值