[动态规划] UVa11584 划分成回文串 (线性DP)(回文串判断)

题目

这里写图片描述

思路

1.先进行回文串打表,判断回文串的方法:枚举中心,然后向两边延伸。
2.状态定义:d(i),字符1~i划分成的最小回文串个数。
3.初状态:d[0]=0,d[1..n]=INF。(INF是为了配合状态转移时的max)
4.答案:d[n]
5.状态转移方程:

d ( i ) = m i n { d ( j ) + 1 | s [ j + 1... i ] }

代码

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define _for(i,a,b) for(int i = (a); i<(b); i++)
#define _rep(i,a,b) for(int i = (a); i<=(b); i++)
using namespace std;

const int INF = 1 << 30;
const int maxn = 1000 + 10;
int n, d[maxn], G[maxn][maxn];
char A[maxn];

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        memset(G, 0, sizeof(G));
        scanf("%s", A + 1);
        n = strlen(A + 1);

        // 回文串的真实打表方法
        _rep(i, 1, n) {
            for (int a = i, b = i; a >= 1 && b <= n; a--, b++) {  // aacaa
                if (A[a] == A[b])
                    G[a][b] = G[b][a] = 1;
                else break;
            }
            for (int a = i, b = i+1; a >= 1 && b <= n; a--, b++) { // acca
                if (A[a] == A[b])
                    G[a][b] = G[b][a] = 1;
                else break;
            }
        }

        _rep(i, 1, n) d[i] = INF;
        d[0] = 0;
        _rep(i, 1, n)
            for (int j = i - 1; j >= 0; j--)
                if (G[j + 1][i])
                    d[i] = min(d[i], d[j] + 1);

        printf("%d\n", d[n]);
    }

    return 0;
}

废话

夏天的蚊子是真的恐怖。。。

猜你喜欢

转载自blog.csdn.net/icecab/article/details/80796166