洛谷oj U3936(分成回文串) 邀请码:a0c9

题目链接:传送门

题目大意:略

题目思路:DP

     先预处理,分别以每个字母为中心处理能形成的回文串,再以两个字母为中心处理能形成的回文串。

     然后 dp[i] 表示1~i 能形成的数目最少的回文串。

     转移方程:if(vis[j][i]==1&&dp[i]>dp[j]+1)dp[i]=dp[j]+1;

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <cctype>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <climits>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define fi first
#define se second
#define ping(x,y) ((x-y)*(x-y))
#define mst(x,y) memset(x,y,sizeof(x))
#define mcp(x,y) memcpy(x,y,sizeof(y))
using namespace std;
#define gamma 0.5772156649015328606065120
#define MOD 1000000007
#define inf 0x3f3f3f3f
#define N 200005
#define maxn 10005
typedef pair<int,int> PII;
typedef long long LL;

int n,m,k,T,ans,cnt;
char str[3111];
bool vis[3001][3001];
int d[3001];
int main(){
    int i,j,group,x,y;
    scanf("%s",str);
    n=strlen(str);
    for(i=0;i<n;++i)for(j=0;i-j>=0&&i+j<n;++j)
        if(str[i-j]==str[i+j])vis[i-j][i+j]=1;
        else break;
    for(i=0;i<n;++i)for(j=1;i-j>=0&&i+j-1<n;++j)
        if(str[i-j]==str[i+j-1])vis[i-j][i+j-1]=1;
        else break;
    for(i=0;i<n;++i){
        if(vis[0][i]){d[i]=1;continue;}
        d[i]=inf;
        for(j=0;j<i;++j)if(vis[j+1][i]&&d[i]>d[j]+1)d[i]=d[j]+1;
    }
    printf("%d
",d[n-1]);
    return 0;
}
原文地址:https://www.cnblogs.com/Kurokey/p/5791079.html