zoukankan      html  css  js  c++  java
  • 【IOI2000】【洛谷1435】回文字串

    问题描述

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

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

    注:此问题区分大小写

    输入格式

    第一行一个整数n(3<=n<=5000)表示字符串的长度

    第二行一个长度为n的字符串

    输出格式

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

    样例输入

    5

    Ab3bd

    样例输出

    2

    题解

    设读入的字符串为s,如果s[i]~s[j]是回文,那么s[i+1]~s[j-1]一定也是回文,满足区间动规的特点。

    设f[i][j]表示s[i]~s[j]变成回文词需要插入的最少字符数,当s[i]==s[j]时,f[i][j]=f[i+1][j-1]+1,否则f[i][j]=min(f[i+1][j],f[i][j-1])+1。

    我用的是记忆化搜索,当i>j时,由于是不合法的状态,我最初返回无穷大,但由于i>j的状态只可能从i==j &&s[i]==s[j]转移过来,所以i>j这个状态的值其实是i==j &&s[i]==s[j]这个状态的值,应该返回0。

     1 #include <cstring>
     2 #include <cstdio>
     3 int n,f[5005][5005];
     4 bool vis[5005][5005];
     5 char s[5005];
     6 int min(int x,int y)
     7 {
     8     return x<y?x:y;
     9 }
    10 int dp(int i,int j)
    11 {
    12     if (i>j) return 0;
    13     if (vis[i][j]) return f[i][j];
    14     vis[i][j]=1;
    15     if (i==j) return f[i][j]=0;
    16     f[i][j]=2e9;
    17     if (s[i]==s[j]) f[i][j]=dp(i+1,j-1);
    18     f[i][j]=min(f[i][j],min(dp(i+1,j),dp(i,j-1))+1);
    19     return f[i][j];
    20 }
    21 int main()
    22 {
    23     int i,j;
    24     scanf("%d",&n);
    25     scanf("%s",s+1);
    26     printf("%d
    ",dp(1,n));  
    27     return 0;
    28 }
  • 相关阅读:
    Spring 中的邮件任务
    Spring 定时任务
    java中同步交互 与 异步交互
    Springboot 版本包冲突
    Derby 配置环境变量
    Springboot中的Web服务Tomcat改为Jetty
    二叉树中和为某一值的路径
    0-Java中this和super的用法总结
    树9:二叉搜索树的后序遍历
    位运算-输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
  • 原文地址:https://www.cnblogs.com/rabbit1103/p/9620373.html
Copyright © 2011-2022 走看看