【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原创,转载请注明出处)

posted on 2011-05-29 15:09  saltless  阅读(466)  评论(0编辑  收藏  举报

导航