Generating Palindromes - lightOJ 1033(区间dp)

题意

给出一个字符串,问最小所需的字符数量使得插入这些字符后,该字符串成为回文串

回文串+区间dp,dp[i][j]表示使给定字符串的i-j段成为回文串的最小插入字符数量, 
在记忆化搜索中有三类情况,一种是i>=j,i>j的段是无意义的,而i=j的段本身肯定是回文,不需插入字符,都是0,之后分c[i]=c[j]和c[i]!=c[j]两类情况,如果c[i]=c[j],继续往这段字符串的中间搜索,即dfs(i+1,j-1),否则我们尝试在最左端和最右端插入字符并取最小值,即min(dfs(i+1,j)+1,dfs(i,j-1)+1)

#include<bits/stdc++.h>
using namespace std;
const int MAXN=110;
char c[MAXN];
int dp[MAXN][MAXN];
bool is_palindrome(int i,int j){
    for(int pos=i;pos<=(i+j)/2;pos++){
        if(c[pos]!=c[j-(pos-i)]) return false;
    }
    return true;
}
void init(){
    memset(dp,-1,sizeof(dp));
}
int dfs(int i,int j){
    int ans=0;
    if(dp[i][j]!=-1) return dp[i][j];//已存在就不用再搜素
    if(i>=j) return dp[i][j]=0;
    else if(c[i]==c[j]){
        return dp[i][j]=dfs(i+1,j-1);//搜素下一区间
    }
    else{
        return dp[i][j]=min(dfs(i+1,j)+1,dfs(i,j-1)+1);//尝试在左右加字符
    }
}
int main(){
    int T,cnt=0;
    scanf("%d",&T);
    while(T--){
        init();
        scanf("%s",c);
        int len=strlen(c)-1;
        if(is_palindrome(0,len)==1){
            printf("Case %d: 0\n",++cnt);
            continue;
        }
        dfs(0,len);
        printf("Case %d: %d\n",++cnt,dp[0][len]);
    }
}

猜你喜欢

转载自blog.csdn.net/lanshan1111/article/details/81810862
今日推荐