DP与回文串

可以对字符串进行增删改变成回文串,每增删改一次算一步,问变成回文串的最少步数。
uva10739
代码:

#include <iostream>
using namespace std;
#include <stdio.h>
#include <cstring>

char str[1005];
int dp[1005][1005];
int main() {
    int T;
    int kase = 0;
    scanf("%d",&T);
    getchar();
    while(T--) {
        gets(str);
        int len = strlen(str);
        for(int i = 0; i < len; i++)
            dp[i][i] = 0;
        for(int i = len - 1; i >= 0; i--) {
            for(int j = i + 1; j < len; j++) {
                if(str[i] == str[j]) 
                    dp[i][j] = dp[i + 1][j - 1];
                else {
                    dp[i][j] = min(dp[i][j - 1],dp[i + 1][j]);
                    dp[i][j] = min(dp[i][j],dp[i + 1][j - 1]) + 1;
                }
            }
        }
        printf("Case %d: %d\n",++kase,dp[0][len - 1]);
    }
    return 0;
}

题目大意:
给出一个字符串,求出最多可以有多少个不同的回文串,一个字母也算一个回文串。
如果i和j的字符是一样的话。
dp[i][j] = dp[i + 1][j] + dp[i][j - 1] + 1;
dp[i][j]可以是加上i和j以后与i + 1, j - 1组成的字符串,也可以不要加入i和j那么就是i + 1,j 加上i,j - 1的时候的回文串个数,但是会重复算了i + 1,j - 1所以要减去,那么就和前面的相抵消了。然后+1是因为加入i和j之后可以和原来的组成一个新的回文串。
如果i和j的字符是不一样的话,
dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1];

代码:

#include <iostream>
using namespace std;
#include <cstring>
#include <stdio.h>

char str[65];
int dp[65][65];
int main() {
    int T;
    scanf("%d",&T);
    getchar();
    while(T--) {
        gets(str);
        int len = strlen(str);
        for(int i =0; i <= len; i++)
    // for(int j =0 ; j <= len; j++)
                dp[i][i] = 1;
        for(int i = len - 1; i >= 0; i--) {
            for(int j = i + 1; j < len; j++) {
                if(str[i] == str[j])
                    dp[i][j] = dp[i + 1][j] + dp[i][j - 1] + 1;
                else
                    dp[i][j] = dp[i + 1][j] + dp[i][j - 1] - dp[i + 1][j - 1];
            }
        }
        printf("%d\n",dp[0][len - 1]);
    }
}

你可能感兴趣的:(DP与回文串)