• [IOI2000] 回文字串


    题目

    Description

    回文词是一种对称的字符串。任意给定一个字符串,通过插入若干字符,都可以变成回文词。此题的任务是,求出将给定字符串变成回文词所需要插入的最少字符数。

    比如 “Ab3bd”插入2个字符后可以变成回文词“dAb3bAd”或“Adb3bdA”,但是插入少于2个的字符无法变成回文词。

    注:此问题区分大小写

    Input

    一个字符串(0<strlen<=1000).

    Output

    有且只有一个整数,即最少插入字符数

    Sample Input

    Ab3bd

    Sample Output

    2

    思路

    这是一道类似区间$dp$的题目;

    我们可以设 $dp[i][j]$ 表示在 $i$ 到 $j$ 区间内,合成回文串需要加多少字母;

    那么很明显我们要考虑两种情况:

    $if~(i==j)$ 

        $dp[i][j]=dp[i+1][j-1]$

    如果 $i$ , $j$  相等,那么两头相等,就不需要多插入什么;

    例如 $dp[abcfa]=a[bcf]$ ;

    $else$

        $dp[i][j]=min(dp[i+1][j],dp[i][j-1])+1$

    否则, 说明串的两头不同,需要多插入$1$字符以保持回文性质,新插入的字符可能在右边,可能在左边;

    例如 $dp[abcdf]=min(dp[abcd],dp[bcdf])+1$ ;

    代码

    #include<bits/stdc++.h>
    #define re register
    typedef long long ll;
    using namespace std;
    inline ll read()
    {
        ll a=0,f=1; char c=getchar();
        while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();}
        while (c>='0'&&c<='9') {a=a*10+c-'0'; c=getchar();}
        return a*f;
    }
    ll n;
    char s[1010];
    ll dp[1010][1010];
    int main()
    {
        scanf("%s",s+1);//输入 
        n=strlen(s+1);
        for(re ll len=2;len<=n;len++)//枚举区间长度 
        for(re ll i=1;i<=n-len+1;i++) 
        {
            ll j=i+len-1;
            if(s[i]==s[j])//如果 i j 相等 
                dp[i][j]=dp[i+1][j-1];
            //那么两头相等,就不需要多插入什么
            else
                dp[i][j]=min(dp[i+1][j],dp[i][j-1])+1;
            //说明串的两头不同,需要多插入 1 字符以保持回文性质
        }
        printf("%lld
    ",dp[1][n]);//没了 
        return 0;
    }
  • 相关阅读:
    spring相关资源
    spring mvc获取request HttpServletRequest
    spring中文乱码问题
    haskell读写文件相关(含二进制)
    grade web的构建约定 convention
    李洪强iOS开发之-实现点击单行View显示和隐藏Cell
    Animated progress view with CAGradientLayer(带翻译)
    关于CAShapeLayer
    CAShapeLayer的使用
    用缓动函数模拟物理动画
  • 原文地址:https://www.cnblogs.com/wzx-RS-STHN/p/13756296.html
Copyright © 2020-2023  润新知