uva 10617 Again Palindrome

来源:互联网 发布:老年网络大学 编辑:程序博客网 时间:2024/06/06 02:03
import java.io.*;import java.math.BigInteger;import java.util.*;public class Main {        public static void main (String [] args) throws Exception {        Scanner scan = new Scanner(System.in);        int cases = Integer.parseInt(scan.nextLine());        while(cases-->0){            String s = scan.nextLine();            BigInteger dp[][] = new BigInteger[s.length()+1][s.length()+1];            for(int i=0;i<s.length()+1;i++){                Arrays.fill(dp[i], BigInteger.ZERO);                dp[i][i] = BigInteger.ONE;            }            for(int gap=1;gap<s.length();gap++){                for(int i=1;i+gap<=s.length();i++){                    int j = gap+i;                    dp[i][j] = dp[i][j].add(BigInteger.ONE).add(dp[i][j-1]);                    for(int k=i;k<j;k++){                        if(s.charAt(k-1)==s.charAt(j-1)){                            dp[i][j] = dp[i][j].add(dp[k+1][j-1]).add(BigInteger.ONE);                        }                    }                }            }            System.out.println(dp[1][s.length()]);        }    }}

首先要稍微转化一下,求有多少种删除方法其实就是求有多少个Palindrome

想到了这一点,解空间其实还是很明显dp[i][j]储存回文数。

但是TMD推公式推了我3个小时。。。
每加一个字母,这个字母本身肯定是一个回文,因为长度为1,所以dp[i][j] = dp[i][j-1]+1;

然后对于所有的K, i<=k<j, 如果arr[k] == arr[j]; 那么arr[k]和arr[j]可以形成一个长度为2的回文,

假设dp[i+1][j-1],也就是中间的部分,假设包含了X 个回文,那么对这X个回文两边各加上arr[k]和arr[j] (arr[k]=arr[j]), 从而得到X个新的回文

所以就是dp[i][j] = dp[i+1][j-1]+1,再补上前面的dp[i][j-1]+1就是结果。稍微有一点复杂,还是能推出来的。

要用BigInteger, 这里WA一次。