回文字符串 (動態規划)


回文字符串

時間限制: 3000 ms  |  內存限制: 65535 KB
難度: 4
描述
所謂回文字符串,就是一個字符串,從左到右讀和從右到左讀是完全一樣的,比如"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;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM