dp[l][r]表示s[l]到s[r]这一段字符串生成回文的最小添加字符个数
决策:
1.若s[l]==s[r]
转移到dp[l+1][r-1]
2.若s[l]!=s[r]
在右部添加一个s[l]
转移到:dp[l+1][r]+1
在左部添加一个s[r]
转移到:dp[l][r-1]+1
需要打印最后结果,决策过程中保存路径,做得比较麻烦,对保存路程、输出决策过程不熟悉
#include<cstdio>
#include<cstring>
#include<stack>
#include<queue>
using namespace std;
#define MAXN 1005
char s[MAXN];
int dp[MAXN][MAXN],path[MAXN][MAXN];
int n;
queue<char> q;
stack<char> st;
int min(int a,int b) {return a<b?a:b;}
int dfs(int l,int r)
{
if(l>r) return 0;
if(dp[l][r]) return dp[l][r];
int ans=MAXN;
if(s[l]==s[r])
{
ans=min(ans,dfs(l+1,r-1));
path[l][r]=1;
}
else
{
int temp1=dfs(l+1,r)+1,
temp2=dfs(l,r-1)+1;
if(ans>temp1)
{
ans=temp1;
path[l][r]=2;
}
if(ans>temp2)
{
ans=temp2;
path[l][r]=3;
}
}
dp[l][r]=ans;
return ans;
}
void out()
{
int l=0,r=n-1;
while(l<=r)
{
if(path[l][r]==1)
{
if(l==r) st.push(s[l]);
else
{
q.push(s[l]);
st.push(s[r]);
}
l++;
r--;
}
else if(path[l][r]==2)
{
q.push(s[l]);
st.push(s[l]);
l++;
}
else if(path[l][r]==3)
{
q.push(s[r]);
st.push(s[r]);
r--;
}
}
while(!q.empty())
{
printf("%c",q.front());
q.pop();
}
while(!st.empty())
{
printf("%c",st.top());
st.pop();
}
printf("\n");
}
int main()
{
while(scanf("%s",s)!=EOF)
{
n=strlen(s);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
dp[i][j]=path[i][j]=0;
dfs(0,n-1);
printf("%d ",dp[0][n-1]);
out();
}
return 0;
}