POJ 1159 Palindrome

寫這個看似簡單的題目才發現自己原來毛都不會(╯‵□′)╯︵┻━┻,加上網上有很多的解析其實講的都不準確,導致了很多理解上的錯誤

這道題就是求字符串s和字符串的逆序串s’的最長公共“子序列”,而並非所謂的最長“子串”,一般來說兩個子串一定是連續的一段字符,而子序列可以是不連續的……

然後問題來了,怎麼求兩個子串的最長公共子序列呢,這裏用的是動態規劃的方法,用數組dp[i][j]來記錄兩個字符串長度爲i和j的前綴的最長公共子序列,然後狀態轉移方程爲如果str1[i] == str2[j]那麼dp[i][j] = dp[i-1][j-1]+1,否則dp[i][j] = max(dp[i-1][j],dp[i][j-1])

p.s. 如果要求的是最長公共子串,那麼當str1[i]!=str1[j]的時候,令dp[i][j] = 0就可以了,這裏dp[i][j]表示的是兩子串的最長公共後綴,所有前綴的最長公共後綴就是最長公共子串。

#include <iostream>
#include <cstdio>
#include <string.h>
using namespace std;

#define maxn 5001

int n;
char str1[maxn]={0};
char str2[maxn]={0};
short dp[2][maxn]={0};
int mymax = 0;

int main(){

    scanf("%d",&n);
    scanf("%s",&str1);
    for(int i=0;i<n;++i){
        str2[i] = str1[n-i-1];
    }
    str2[n] = '\0';
    //printf("%s\n",str2);
    for(int i=1;i<=n;++i){
        for(int j=1;j<=n;++j){
            if(str1[i-1]==str2[j-1])
                dp[i%2][j] = dp[(i-1)%2][j-1]+1;
            else
                dp[i%2][j] = max(dp[(i-1)%2][j],dp[i%2][j-1]);
            if(dp[i%2][j]>mymax)
                mymax = dp[i%2][j];
        }
    }
    printf("%d\n",n-mymax);
    //system("pause");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章