【问题描述】
回文词是一种对称的字符串——也就是说,一个回文词,从左到右读和从右到左读得到
的结果是一样的。任意给定一个字符串,通过插入若干字符,都可以变成一个回文词。你的
任务是写一个程序,求出将给定字符串变成回文词所需插入的最少字符数。
比如字符串“Ab3bd ”,在插入两个字符后可以变成一个回文词(“ dAb3bAd ”或
“Adb3bdA”)。然而,插入两个以下的字符无法使它变成一个回文词。
【输入文件】
第一行包含一个整数 N,表示给定字符串的长度,3<=N<=5000
第二行是一个长度为 N 的字符串,字符串由大小写字母和数字构成。
【输出文件】
一个整数,表示需要插入的最少字符数。
【输入样例】
5
Ab3bd
【输出样例】
回文词是一种对称的字符串——也就是说,一个回文词,从左到右读和从右到左读得到
的结果是一样的。任意给定一个字符串,通过插入若干字符,都可以变成一个回文词。你的
任务是写一个程序,求出将给定字符串变成回文词所需插入的最少字符数。
比如字符串“Ab3bd ”,在插入两个字符后可以变成一个回文词(“ dAb3bAd ”或
“Adb3bdA”)。然而,插入两个以下的字符无法使它变成一个回文词。
【输入文件】
第一行包含一个整数 N,表示给定字符串的长度,3<=N<=5000
第二行是一个长度为 N 的字符串,字符串由大小写字母和数字构成。
【输出文件】
一个整数,表示需要插入的最少字符数。
【输入样例】
5
Ab3bd
【输出样例】
2
分析:由于回文是向右和向左读的都是一样的,那么我们可以这样思考,建立另一个数组,该数组是原数组的反方向的,那么假设两者读的都是一样的,那么这两者就是相同的,也就是说他们两者组合成了回文,因此题目就化为了求最长公共子序列的问题了
code:
滚动数组优化空间
另外我查阅资料更新本文章的另一种方案,可以模拟一下,本算法不是很难的:
通过前面的分析我们很容易想到这样的算法:
对于一个序列 S 只要看它的左右端的字符是否相同,如果相同那么就看除掉两端字符的新串
要添的字符个数了;如果不同,就在它左面添上右断的字符然后考虑去掉新序列两端的字符
后的串要添的字符。或者在右面添上左端的字符,在考虑去掉添了字符后新串左右两端字符
得到的新串要添的字符。
设计一个二维状态 opt[L,i]表示长度是 L+1,起点是 i 的序列变成回文词要添的字符的个数。
阶段就是字符的长度,决策要分类,即 S[i] 和 S[i+L]是否相等。
状态转移方程:
min(opt[L-1,i]+1, opt[L-1,i+1]+1) (s[i]<>s[i+L])
opt[L,i]=
min(opt[L-1,i]+1, opt[L-1,i+1]+1,opt[L-2,i+1]) (s[i]=s[i+L])
复杂度:
空间复杂度=状态数 O(N2)
时间复杂度=状态数 O(N2)* 转移代价 O(1)=O(N2)
由于空间复杂度较高,仍然要用滚动数组