Palindrome
As an example, by inserting 2 characters, the string "Ab3bd" can be transformed into a palindrome ("dAb3bAd" or "Adb3bdA"). However, inserting fewer than 2 characters does not produce a palindrome.
5 Ab3bd
2
题意:
给出一个数字,代表一个字符串的长度,下一行是一个字符串,让你求出至少加几个字符可以把这个字符串变成回文字符串(回文是啥?百度呗...)....
分析,需要求最少加多少字符形成回文串,那么可以这样考虑,因为是想要回文的字符串,那么就拿字符串本身和本身反过来比较,先求出最长公共子序列,为什么呢,想想看,如果公共子字符有很多,那么在加字符的时候不是就可以少考虑很多了吗?也就是说,让这个字符串的长度减去最长公共子序列,求得的就是不能形成回文匹配的数值,也就是所需要的数值!!
lcs ,比较经典的做法就是开个数组进行动态打表,但是,这个题要求的数据比较大,按一般的要求开二维数组会超内存(2500万啊),然后想啊想
,重新理解了一下这个算法的运转过程,才发现一个比较神奇的地方:在数组操作的时候,数组的前部分数据已经没有了实际意义,也就是浪费了空间!!
因为这个算法吗,从头到尾操作的只有两行的数组(或者两列),然后只需要对下标取余运算,就相当于这个数组可以来回储存有效值,而且不会超内存!
自己也就是大胆想出来的做法,没想到学长竟然说这是所谓的滚动数组的实现,嘿嘿,有时候感觉真的可以多想一点,至少拓展思路没什么错的,多思考才能发现更多别人发现不了的东西!!哈哈~~
ps:自己模拟一下lcs的运转过程,就会发现,第一维数组完全不必要开太大,够用就行...
#include<stdio.h>
#include<string.h>
#define max(a,b) a>b?a:b;
char x[5005];
int y[5][5005];//!!!这里完全可以把第一维开到2,不过开多点也没错...
int main()
{
int i,j,len;
while(~scanf("%d",&len))
{
getchar();
scanf("%s",x);
memset(y,0,sizeof(y));//清零
for(i=1;i<=len;++i)
{
for(j=1;j<=len;++j)
{
if(x[i-1]==x[len-j])
{
y[i%5][j]=y[(i-1)%5][j-1]+1;//完全和平时的一样
}
else
{
y[i%5][j]=max(y[i%5][j-1],y[(i-1)%5][j]);
}
}
}
printf("%d\n",len-y[len%5][len]);//这个就是需要的数值
}
return 0;
}