P1435 回文字串
题解:
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示前
i
i
i个字符与后
j
j
j个字符构成回文串需要插入的最少字符数。
则有
{
d
p
[
i
]
[
j
]
=
d
p
[
i
−
1
]
[
j
−
1
]
,
s
[
i
]
=
=
s
[
n
−
j
+
1
]
d
p
[
i
]
[
j
]
=
m
i
n
(
d
p
[
i
−
1
]
[
j
]
,
d
p
[
i
]
[
j
−
1
]
)
+
1
,
s
[
i
]
̸
=
s
[
n
−
j
+
1
]
\begin{cases}dp[i][j] = dp[i-1][j-1],&\text{$s[i]==s[n-j+1]$}\\dp[i][j] = min(dp[i - 1][j],dp[i][j -1]) + 1,&\text{$s[i]\not=s[n-j+1]$}\end{cases}
{dp[i][j]=dp[i−1][j−1],dp[i][j]=min(dp[i−1][j],dp[i][j−1])+1,s[i]==s[n−j+1]s[i]̸=s[n−j+1]
至于边界就是
d
p
[
i
]
[
0
]
=
d
p
[
0
]
[
i
]
=
i
dp[i][0] = dp[0][i] = i
dp[i][0]=dp[0][i]=i。前
i
i
i个字符和后
0
0
0个至少需要插入
i
i
i个字符,后
j
j
j个字符和前
0
0
0个字符至少需要插入
j
j
j个字符。
代码
#include<bits/stdc++.h>
using namespace std;
int dp[1010][1010];
int main()
{
#ifndef ONLINE_JUDGE
freopen("input.in","r",stdin);
#endif
string s;
cin>>s;
int n = s.length();
for(int i = 1; i <= n; ++i) {
dp[i][0] = dp[0][i] = i;
}
for(int i = 1; i <= n; ++i) {
for(int j = 1; i + j <= n; ++j) {
if(s[i - 1] == s[n - j]) {
dp[i][j] = dp[i - 1][j - 1];
}else{
dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1;
}
}
}
int ans = 1e9;
for(int i = 0; i < n; ++i) {
ans = min(ans,min(dp[i][n - i],dp[i][n - i - 1]));
}
cout<<ans<<endl;
return 0;
}