【One more】poj1159 Palindrome
又是一道水题…总觉得今天光做水题了…
.
题目是poj1159(http://poj.org/problem?id=1159),属于一道简单的动归。
题目如下。
【题目描述】
给你一个字符串,你可以向里面的任意位置插入字符,问让这个串成为回文串最少要插入多少字符。
【输入格式】
第一行一个整数n,代表串的长度。
下面是一个字符串,即你需要处理的串。
【输出格式】
一个整数,表示使给定串成为回文串最少要插入的字符数。
【样例输入】
5
Ab3bd
【样例输出】
2
【数据范围】
3<=n<=5000
其实这道题的n<=1000版本我在以前发出过题解(怎么我的题解全是水题XD),链接在这里:http://www.cnblogs.com/saltless/archive/2010/08/10/1796198.html 这回是n<=5000的,其实用上次的方法也能过,这回贴的代码使用循环数组记录状态,可以大大节省空间。
关于这道题的方法详见上面链接中的解答,本文着重说一下空间的优化。
.
空间复杂度O(n2)代码:
program poj1159; var s:ansistring; f:array[0..5005,0..5005]of integer; i,j,l:integer; function min(x,y:integer):integer; begin if x>y then exit(y) else exit(x); end; begin readln(l); readln(s); for i:=2 to l do for j:=i-1 downto 1 do begin if s[i]=s[j] then f[j,i]:=f[j+1,i-1] else f[j,i]:=min(f[j+1,i],f[j,i-1])+1; end; writeln(f[1,l]); end.
其实很好发现,对于每个i,整个状态转移的过程只和f[x,i]与f[x,i-1]有关。这样,原来开的n2的数组就完全是浪费空间,我们只要开两个数组记录f[x,i]和 f[x,i-1]就行了!
我用f[1,x]代表原来的f[x,i-1],f[2,x]是f[x,i],f[3,x]作为空数组,起fillchar的作用。这样在j循环一遍以后,加入下列语句,就可以实现空间的循环使用:
f[1]:=f[2];
f[2]:=f[3];
其实也可以只用f[0,x]和f[1,x]两个域就可以,用k做标记,记录现在在用f[0]还是f[1],最后用k:=1-k进行切换就行了(详见:http://blog.sina.com.cn/s/blog_6635898a0100hnpz.html)。
.
参考代码:
program poj1159; var s:ansistring; f:array[1..3,0..5005]of integer; i,j,l:integer; function min(x,y:integer):integer; begin if x>y then exit(y) else exit(x); end; begin readln(l); readln(s); for i:=2 to l do begin for j:=i-1 downto 1 do if s[i]=s[j] then f[2,j]:=f[1,j+1] else f[2,j]:=min(f[2,j+1],f[1,j])+1; f[1]:=f[2]; f[2]:=f[3]; end; writeln(f[1,1]); end.
本文地址:http://www.cnblogs.com/saltless/archive/2011/05/29/2062113.html
(saltless原创,转载请注明出处)