回文字符串
- 描述
- 所謂回文字符串,就是一個字符串,從左到右讀和從右到左讀是完全一樣的,比如"aba"。當然,我們給你的問題不會再簡單到判斷一個字符串是不是回文字符串。現在要求你,給你一個字符串,可在任意位置添加字符,最少再添加幾個字符,可以使這個字符串成為回文字符串。
- 輸入
-
第一行給出整數N(0<N<100)
接下來的N行,每行一個字符串,每個字符串長度不超過1000. - 輸出
- 每行輸出所需添加的最少字符數
- 樣例輸入
-
1 Ab3bd
- 樣例輸出
-
2
- 來源
- IOI 2000
- 上傳者
- //很神奇的一道動態規划,
- //輸入字符串后,逆序,然后求原串與逆序串的最長公共子序列,問題是怎么確定這樣是正確的呢?
- //證明:
- s=a1a2a3..an;s'=a1'a2'a3'...a'(n+m); s'包含s,且s'是回文串,求最小的m,s'的性質:1.最短,2回文,3原串
- //的順序不變
- //設 在 s'卻不在s中的元素記為集合A, a'i=a'(n+m-i+1) 假如屬於A,那么性質一就不滿足,所以a'i和a'(n+m-i+1)中
- //要么都不屬於A,要么有一個屬於A,這樣找出最小屬於A的、就是找到原串的最大配對。即原序和逆序的最長公共子序列
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
int dp[1003][1003];
char s[1003];
int main()
{
int n;
scanf("%d",&n);getchar();
while(n--)
{
scanf("%s",s);
int l=strlen(s);
for(int i=0;i<l;i++)
for(int j=l-1;j>=0;j--)
{
int k=l-1-j;
if(s[i]==s[j])
dp[i+1][k+1]=dp[i][k]+1;
else
dp[i+1][k+1]=dp[i][k+1]>dp[i+1][k]?dp[i][k+1]:dp[i+1][k];
}
printf("%d\n",l-dp[l][l]);
}
return 0;
}
// poj的這題連接 http://poj.org/problem?id=1159
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
short dp[5003][5003];//這里要用short,不然會超內存限制,不過可以用滾動數組、呵呵
char s[5003];
int main()
{
int l;
while(scanf("%d",&l)!=EOF)
{ getchar();
scanf("%s",s);
for(int i=0;i<l;i++)
for(int j=l-1;j>=0;j--)
{
int k=l-1-j;
if(s[i]==s[j])
dp[i+1][k+1]=dp[i][k]+1;
else
dp[i+1][k+1]=dp[i][k+1]>dp[i+1][k]?dp[i][k+1]:dp[i+1][k];
}
printf("%d\n",l-dp[l][l]);
}
return 0;
}