zoukankan      html  css  js  c++  java
  • UVA 10617 Again Palindrome

    这道题因为那个score out给我蒙住了,其实说白了,就是给你一串字符串,让你从中找出有多少回文字串,这个回文字串可以是一个字母,也可以是多个。

    既然是动态规划题:我们肯定要这样想,让我们求长度为len的字符串有多少回文字串,那么长度为len-1的字符串有多少回文子串呢,如果我们求出了len-1的字符串,那么长度为len的字符串的回文字串的个数可不可以通过这个来求出呢,那么长度为len-1的母串可不可以通过len-2的母串求出呢,。。。。。

    当然上面的过程当然是可以的:

    接下来想一个串如果两端不等的话(ABBO):
    那么它的方式就等于 1 + ABB里面的种数 + BBO里面的种数 – 两个集合重复的部分

    如果两端相等的话(ABOA):
    那么它的方式就等于 1 + ABO里面的种数 + BOA里面的种数 + BO里面的种数(因为BO里面的每种回文在两边同时加上相等的字符还会是回文“B”、“O”—> “ABA”、“AOA”) + 1(两个端点也可以组成一个回文) – 前两个加数里重复的部分。

    所以状态转移方程就可以初步定型 :
    d[i][j]=d[i][j-1]+d[i+1][j]-temp(如果s[i]==s[j])
    d[i][j]=d[i][j-1]+d[i+1][j]+d[i+1][j-1]+1-temp(如果s[i]!=s[j])
    上面两式中的temp 表示d[i][j-1]和d[i+1][j]这么多中方法中重复的种数

    代码如下:

    #include<stdio.h>
    #include<string.h>
    #define MAXN 65
    long long b[MAXN][MAXN];
    char s[MAXN];
    int n;
    void solve()
    {
        int len = strlen(s);
        for(int i = 0; i < len; i ++)
        b[i][i] = 1;
        for(int i = 1; i < len; i ++)
            for(int j = 0; i+j < len; j ++)
            {
                long long t;
                if(s[j] != s[i+j]) 
                {
                    if(i+j-1 < j+1) t = 0;
                    else t = b[j+1][i+j-1];
                    b[j][i+j] = b[j][i+j-1] + b[j+1][i+j] - t;
                }
                else
                {
                    b[j][i+j] = b[j][i+j-1] + b[j+1][i+j] + 1;
                }
            }
        printf("%lld\n",b[0][len-1]);
    }
    void input()
    {
        while(~scanf("%d",&n))
        while(n --)
        {
            scanf("%s",s);
            solve();
        }
    }
    int main()
    {
        input();
        return 0;
    }
  • 相关阅读:
    查询父节点parentNode
    008-流程控制 case 语句
    007-流程控制 if 语句
    006-条件判断
    005-sort 命令使用
    004-sed 命令使用
    003-awk 命令使用
    002-printf 命令用法
    001-cut 的用法
    002-变量
  • 原文地址:https://www.cnblogs.com/yuzhaoxin/p/2472602.html
Copyright © 2011-2022 走看看