回文串 --- 动态dp UVA 11584

题目链接:

https://cn.vjudge.net/problem/34398/origin

本题的大意其实很简单,就是找回文串,大致的思路如下:

1. 确定一个回文串,这里用到了自定义的check函数原理如下:

传入le, ri两个值(定义从1开始), s+1 = aaadbccb.

    a a a d b c c b

1 2 3 4 5 6 7 8

比如,le = 5, ri = 8. 则s[5] == s[8]成立

le++ ri--

再比较 s[6] == s[7]? 成立

le++, ri--. 此时, le > ri  return true.

所以,这就是一个字符串。

2. 动态dp

定义个f[MX]函数用于动态dp

首先初始化f[n] = n;

然后check(j. i);

如果返回成true则进行动态规划 f[i] = min(f[i], f[j-1]+1)

3. 输出f[n]即可

下面是AC代码:

#include <iostream>
#include <cstdio>
#include <string.h>

using namespace std;
const int MX = 1000+10;
char s[MX];
int f[MX];
bool check(int le, int ri)
{
    while(le <= ri)
    {
        if(s[le] != s[ri]) return false;
        le++; ri--;
    }
    return true;
}

int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        memset(f, 0, sizeof(f));
        scanf("%s", s+1); //从第二位,也就是1开始填字符
        int n = strlen(s+1); //计算s+1的长度
        for(int i = 1; i <= n; ++i) //动态dp
        {
            f[i] = i; //初始化,每个均为一
            for(int j = i; j > 0; j--)
            {
                if(check(j, i)) f[i] = min(f[i], f[j-1]+1);
            }
        }
        printf("%d\n", f[n]);
    }

}

原文地址:https://www.cnblogs.com/mpeter/p/10292086.html

时间: 2024-08-02 14:33:46

回文串 --- 动态dp UVA 11584的相关文章

UVa 10617 Again Palindrome(回文串区间DP)

UVa 10617 Again Palindrome(经典回文串区间DP) 题意: 给定一个字符串s,对s进行删除操作,使得剩下的子串是回文字符串,问最多有多少种这种子串. 思路: 涉及到回文字符串,首先要想到的肯定是区间DP,如何写出状态转移方程? 直接从题意切入:dp[i, j]表示区间[i, j]最多有多少个这样的子串. 1. s[i] == s[j] 去掉s[i],则一个子问题就是dp[i+1, j]; 去掉s[j],另一个子问题就是dp[i, j-1]; 显然这两个子问题是会有重叠的,

回文串区间dp

UVa 10739 String to Palindrome(经典回文串区间DP) 题意: 给定一个字符串,可以对其进行删除,插入,替换操作. 问最少经过几次操作,可以使这个字符串变成回文字符串. 思路: 看得别人的 题解,最优化问题,用较为直接的方法处理时发现情况很复杂,很多时候就要考虑动态规划了.先从整体出发,由大到小,看往少一个两个元素的情况进行最优递归,如何得到结果. (这里区间DP即是不断向两侧扩大规模) (1)如果最外层两个字符相同,s[0]==s[n],那么这两个字符外侧肯定不用考

关于回文串的DP问题

问题1:插入/删除字符使得原字符串变成一个回文串且代价最小 poj 3280 Cheapest Palindrome 题意:给出一个由m中字母组成的长度为n的串,给出m种字母添加和删除花费的代价,求让给出的串变成回文串的代价. Sol: 插入和删除等价,因此只需要保留 min(插入代价,删除代价)作为调整字符串的代价 如果 s[i]==s[j],那么将区间(i,j)变为回文串的代价和将区间(i+1,j-1)变为回文串的代价相同,因为此时不需要修改 如果不同,必然要将 s[i]和s[j]改为同一字

UVA - 11584 划分字符串的回文串子串; 简单dp

/** 链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34398 UVA - 11584 划分字符串的回文串子串: 简单dp 题目大意: 给一个字符串, 要求把它分割成若干个子串,使得每个子串都是回文串.问最少可以分割成多少个. 定义:dp[i]表示前0~i内的字符串划分成的最小回文串个数: dp[i] = min(dp[j]+1 | j+1~i是回文串); 先预处理flag[i][j]表示以i~j内的字符串为回文串

Uva 11584,划分成回文串

题目链接:https://uva.onlinejudge.org/external/115/11584.pdf 题意: 一个字符串,将它划分一下,使得每个串都是回文串,求最少的回文串个数. 分析: d(i)到第 i 个字符时的最优解(即最少划分为几个回文串),就有方程  d(i) = min(d(j)) + 1;(其中s[j+1,i]要是回文串). 这样一来,枚举就是O(n^2)的复杂度,如果按照普通的判断s[j+1,i]是否是回文串,时间复杂度为O(n^3);先用O(n^2)的复杂度预处理is

Uva 10617 Again Palindrome (DP+回文串)

Problem I Again Palindromes Input: Standard Input Output: Standard Output Time Limit: 2 Seconds A palindorme is a sequence of one or more characters that reads the same from the left as it does from the right. For example, Z, TOT and MADAM are palind

UVa 11584 划分成回文串

https://vjudge.net/problem/UVA-11584 题意: 给出一串字符,把它划分成尽量少的回文串. 思路: 用d[i]表示划分到i时所能划分的最小个数,转移方程为d[i]=min{d[i],d[j]+1},当然前提是j+1~i是回文串,我们可以预处理计算出所有的回文串,这样转移时就比较方便. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<s

UVA 11584 Partitioning by Palindromes 划分回文串 (Manacher)

d[i]表示前面i个字符划分成的最小回文串个数,那么转移i字符和之前的某个字符j构成回文串形成的新划分,所以要判断前面的字符j+1到i是不是回文串,可以用Manacher算法预处理出来. #include <iostream> #include <algorithm> #include <cstring> #include<cstdio> using namespace std; const int MAX = 1042; int len, p[2*MAX]

NYOJ 1023 还是回文(DP,花最少费用形成回文串)

1 /* 2 题意:给出一串字符(全部是小写字母),添加或删除一个字符,都会产生一定的花费. 3 那么,将字符串变成回文串的最小花费是多少呢? 4 5 思路:如果一个字符串增加一个字符 x可以形成一个回文串,那么从这个字符串中删除这个字符 x 6 同样也能形成回文串! 7 所以我们只记录删除,和增加这个字符 x 的最小的费用就好了!->转变成添加多少个字符形成回文串费用最少! 8 9 str[i]!=str[k] 10 dp[i][j]=min(dp[i][j-1]+cost[str[k]-'a