It's not who you are underneath, it's what you do that defines you

线性DP——回文词-IOI2000(未完结)

 回文词-IOI2000

【问题描述】
回文词是一种对称的字符串——也就是说, 一个回文词, 从左到右读和从右到左读得到的结果是一样的。 任意给定一个字符串, 通过插入若干字符, 都可以变成一个回文词。 你的任务是写一个程序, 求出将给定字符串变成回文词所需插入的最少字符数。
比如字符串“ Ab3bd”,在插入两个字符后可以变成一个回文词( “ dAb3bAd” 或“ Adb3bdA”) 。然而,插入两个以下的字符无法使它变成一个回文词。


【输入文件】
第一行包含一个整数N,表示给定字符串的长度, 3<=N<=5000
第二行是一个长度为N的字符串,字符串由大小写字母和数字构成。


【输出文件】
一个整数,表示需要插入的最少字符数。


【输入样例】
5
Ab3bd


【输出样例】
2

 

------------------------------------分割----------------------------------

首先,由于可以在任何地方进行插入,明显是在提醒:向最长公共子序列上想

为什么不是子串?

子串强调连续,但子序列不用(在任何地方进行插入)

对于任意的字符串,都可以和他的反串进行如下操作(举例说明):

ASD4456

6544DSA

附上代码

 1 #include <iostream>
 2 #include <cstring>
 3 using namespace std;
 4 int n,maxi,dp[5010][5010];
 5 char sin[5010],sso[5010];
 6 int main()
 7 {
 8     cin>>n;
 9     cin>>sin+1;
10     for(int i=1;i<=n;i++)
11     {
12         sso[i]=sin[n-i+1];
13     }
14     for(int i=1;i<=n;i++)
15     {
16         for(int j=1;j<=n;j++)
17         {
18              if(sin[i]==sso[j]) dp[i][j]=dp[i-1][j-1]+1;
19              else dp[i][j]=max(dp[i][j-1],dp[i-1][j]);
20         }
21     }
22     cout<<n-dp[n][n];
23 }

 

posted @ 2019-07-30 10:19  lihaolin  阅读(234)  评论(0编辑  收藏  举报