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

你可能感兴趣的:(more)