线性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 }