Palindrome
Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4139 Accepted Submission(s): 1414
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.
題目翻譯:
輸入一個數n,下一行輸入n長的字符串,輸出最少需要添加多少個字符才能將其變成迴文串(大小寫字母不同,包含數字)
思路:
迴文,即正着讀和倒着讀一樣,那就以正讀順序爲橫標,逆讀順序爲縱標,求其最長公共子序列(LCS),拿(n-最長公共序列),既是最少要添的字符數;
另外,直接建立5000*5000矩陣會爆內存,所以採用滾動數組,根據LCS原理,每次比較,行=列時,左上角+1,否則取左邊和上邊的較大者,因此每次運算只涉及兩行,其餘的都是無效行,因此數組開2*5000足以,行號在0-1間交替滾動。
一道又氣又惱的題,代碼裏記錄長度的滾動數組應爲int,結果順手寫進了char,導致存進整數輸出整數在本地可以運行,在oj上一直WA,出錯在定義行,找了好久才發現,引以爲戒
#include<cstdio>
#include<cstring>
#define MAX 5050
#define gun (m?0:1)//由此式實現m在0-1間切換,亦可寫成(m+1)%2
int N;
char a[MAX],b[MAX];
int s[2][MAX];//滾動數組,兩行足以;定義出錯在此
int max(int a,int b)//這個可寫成#define max(a,b) a>b?a:b代替
{
return a>b?a:b;
}
int lcs(char a[],char b[])
{
int m=1;
memset(s,0,sizeof(s));//清空滾動數組
for(int i=0;i<N;i++)
{
for(int j=0;j<N;j++)
{
if(a[i]==b[j])
s[m][j+1]=s[gun][j]+1;//另一行對線位+1
else
s[m][j+1]=max(s[m][j],s[gun][j+1]);//左一位和上一位較大者
}
m=gun;//換行
}
return s[gun][N];
}
int main()
{
while(scanf("%d",&N)!=EOF)
{
getchar();//吸收換行符
for(int n=0;n<N;n++)
scanf("%c",&a[n]);
for(int i=0,j=N-1;j>=0;i++,j--)
b[i]=a[j];//逆轉數組
a[N]='\0';b[N]='\0';
printf("%d\n",N-lcs(a,b));
}
return 0;
}