题解:P13549 热辣滚烫
题目大意
我们将会得到两个字符串 \(s1\) 和 \(s2\),我们需要检验是否可以在字符串 \(s1\) 上某个字符之后或者 \(s1\) 之前添加一个字符串(可以为空串)从而使得更改后的字符串 \(s1'\)= 字符串 \(s2\)。
题目分析
其实经过思考过后我们就可以发现,这道题目就是检验字符串 \(s1\) 是否为字符串 \(s2\) 的子序列。那么,我们可以尝试通过一个双指针的方式来检验字符串 \(s1\) 是否为字符串 \(s2\) 的子序列。
那么具体要怎么实现呢?
我们可以设定两个指针 \(p1\) 和 \(p2\)。\(p1\) 指向字符串 \(s1\) 的开头;\(p2\) 指向字符串 \(s2\) 的开头。接下来,我们不断移动指针 \(p1\) 和 \(p2\)。如果 \(s1\) 的 \(p1\) 位置的字符与 \(s2\) 的 \(p2\) 位置的字符相等,那么就让 \(p1\) 向后移动一格。同时保持 \(p2\) 的移动。代码实现如下:
#include<bits/stdc++.h>
using namespace std;
int t,len1,len2,p,i,j;
void fun()
{
string s1,s2;
i=j=0;
scanf("%d%d",&len1,&len2);
cin>>s1>>s2;
if(len1>len2)
{
printf("No");
return ;
}
while(i<len1&&j<len2)
{
if(s1[i]==s2[j]) i++;//若字符一样,i++
j++;//保持j指针移动
}
if(i==len1) printf("Yes");
else printf("No");
}
int main()
{
scanf("%d",&t);
while(t--)
{
fun();
if(t!=0) printf("\n");
}
return 0;
}
接下来,当你高高兴兴地提交完代码之后,你就会发现,WA 了。
那为什么会答案错误呢?
经过一番检查后,我们会发现:只可以在一个字符的后边或者 \(s1\) 的前面添加字符串。
而如果像上面的代码一样,就可能会导致一些需要添加多个字符串的字符串 \(s1\) 也判定为合法。所以我们需要遍历字符串 \(s1\),检查是否有可能在一个字符的后边添加字符串从而达到更改后字符串 \(s1'\) = 字符串 \(s2\)。
接下来,我们就可以按照这个算法来实现代码了。
AC 代码
#include<bits/stdc++.h>
using namespace std;
int T,n,m,l,flag,pos;
void fun()
{
string s1,s2;
scanf("%d%d",&n,&m);
cin>>s1>>s2;
if(n>m)//如果s1长度大于s2长度,就一定非法
{
printf("No");
return ;
}
flag=1;
for(int k=1;k<=n;k++)
{
if(s1[n-k]!=s2[m-k])
{
flag=0;
break;
}
}
if(flag==1)//如果字符串s1可以通过在s1前面添加字符串的方式使得更改后字符串与s2相同,直接判定合法
{
printf("Yes");
return ;
}
l=m-n;
pos=0;
while(pos<n&&pos<m&&s1[pos]==s2[pos]) pos++;//最长公共部分
if(pos+l<=m)//否则判定是否可以通过在一个字符后添加一个字符串使得更改后字符串与s2相同
{
flag=1;
for(int k=0;k<n-pos;k++)
{
if(s1[pos+k]!=s2[pos+l+k])//若有一个字符不同,判定为非法
{
flag=0;
break;
}
}
if(flag==1)
{
printf("Yes");
return ;
}
}
printf("No");
}
int main()
{
scanf("%d",&T);
while(T--)//处理多组数据
{
fun();
if(T!=0) printf("\n");//优化行末空格输出
}
return 0;
}
总结
这道题目需要通过严密的思考得出正确的解决思路,一定需要仔细推敲每个解决思路是否存在问题。

浙公网安备 33010602011771号