题意
给定两个字符串 s s s 和 t t t,可以对 s s s 字符串进行如下的两种操作:
-
对字符串 s s s 的任意位置删去 A A A 字符。
-
对字符串 s s s 的任意位置插入 B B B 字符。
问是否可以进行若干次操作后将 s s s 变为 t t t。
解决
考虑动态规划做法,时间复杂度 O ( l s × l t ) O(l_s \times l_t) O(ls×lt)。
一个动态规划数组 f f f, f i , j \mathit{f}_{i,j} fi,j 表示 s i s_i si 和 t j t_j tj 是否能匹配。
动态规划分成两个阶段解决。
- 初始化:
f 0 , 0 = 1 \mathit{f}_{0,0}=1 f0,0=1(这个前往别忘)
{ f i , 0 = f i , 0 ∣ f i − 1 , 0 s i = A f 0 , i = f 0 , i ∣ f 0 , i − 1 t i = 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
- 动态规划:
f i , j = { f i , j ∣ f i − 1 , j s i = A f i , l ∣ f i , l − 1 t i = B f i , j ∣ f i − 1 , j − 1 s i = t j \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
最后判断 f l s , l t \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;
}