题意
给定两个字符串 sss 和 ttt,可以对 sss 字符串进行如下的两种操作:
-
对字符串 sss 的任意位置删去 AAA 字符。
-
对字符串 sss 的任意位置插入 BBB 字符。
问是否可以进行若干次操作后将 sss 变为 ttt。
解决
考虑动态规划做法,时间复杂度 O(ls×lt)O(l_s \times l_t)O(ls×lt)。
一个动态规划数组 fff,fi,j\mathit{f}_{i,j}fi,j 表示 sis_isi 和 tjt_jtj 是否能匹配。
动态规划分成两个阶段解决。
- 初始化:
f0,0=1\mathit{f}_{0,0}=1f0,0=1(这个前往别忘)
{fi,0=fi,0∣fi−1,0si=Af0,i=f0,i∣f0,i−1ti=B\begin{cases}\mathit{f}_{i,0}=\mathit{f}_{i,0}|\mathit{f}_{i-1,0}&s_i=A\\\mathit{f}_{0,i}=\mathit{f}_{0,i}|\mathit{f}_{0,i-1}&t_i=B\end{cases}{fi,0=fi,0∣fi−1,0f0,i=f0,i∣f0,i−1si=Ati=B
- 动态规划:
fi,j={fi,j∣fi−1,jsi=Afi,l∣fi,l−1ti=Bfi,j∣fi−1,j−1si=tj\mathit{f}_{i,j}=\begin{cases}\mathit{f}_{i,j}|\mathit{f}_{i-1,j}&s_i=A\\\mathit{f}_{i,l}|\mathit{f}_{i,l-1}&t_i=B\\\mathit{f}_{i,j}|\mathit{f}_{i-1,j-1}&s_i=t_j\end{cases}fi,j=⎩⎨⎧fi,j∣fi−1,jfi,l∣fi,l−1fi,j∣fi−1,j−1si=Ati=Bsi=tj
最后判断 fls,lt\mathit{f}_{l_s,l_t}fls,lt 是否为真即可。
代码
#include<bits/stdc++.h>
using namespace std;
string s,t;
bool f[1010][1010];
int main()
{
cin>>s>>t,f[0][0]=1,s='0'+s,t='0'+t;
for(int i=1;i<s.size();i++) if(s[i]=='A') f[i][0]=f[i][0]|f[i-1][0];
for(int i=1;i<t.size();i++) if(t[i]=='B') f[0][i]=f[0][i]|f[0][i-1];
for(int i=1;i<s.size();i++)
{
for(int j=1;j<t.size();j++)
{
if(s[i]=='A') f[i][j]=f[i][j]|f[i-1][j];
if(t[j]=='B') f[i][j]=f[i][j]|f[i][j-1];
if(s[i]==t[j]) f[i][j]=f[i][j]|f[i-1][j-1];
}
}
if(f[s.size()-1][t.size()-1]) cout<<"YES";
else cout<<"NO";
return 0;
}
文章讨论了如何通过动态规划方法判断两个字符串s和t是否可以通过插入和删除A、B字符操作变为相同。通过构建动态规划数组f来表示两个子串的匹配状态,最终检查f数组的对应元素是否为真。
956

被折叠的 条评论
为什么被折叠?



