思路
- 双指针思路
- 两个指针分别从前往后扫,如果a[i]==b[j],i++
- 扫的过程中,每轮 j++
- 扫完b后,如果i到了n,完全匹配,否则匹配失败
- 为什么双指针正确
- 优先在b中找匹配a[i]的第一个b[j](贪心思路),此时选择b[j]并不会影响b[j]后面的匹配结果
- 假设存在一种匹配模式:a[i]匹配b[k],k>j,则一定可以将k变成j,即 变成 双指针匹配模式
- 可以证明,任何满足匹配的匹配模式都可以转换为双指针匹配模式,即 双指针模式是最优的。如果双指针都不能匹配成功,那么任何匹配方式都不能匹配成功了
版本1
当b到末尾了,就及时止损
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=1e5+10;
int n,m;
int a[N],b[N];
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<m;i++) scanf("%d",&b[i]);
string res="Yes";
for(int i=0,j=0;i<n;i++){
while(j<m && b[j]!=a[i]) j++;
if(j>=m){
res="No";
break;
}
j++;
}
cout<<res<<endl;
return 0;
}
版本2
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=100010;
int n,m;
int a[N],b[N];
int main(){
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<m;i++) scanf("%d",&b[i]);
int i=0,j=0;
while(i<n&&j<m){
if(a[i]==b[j]) i++;
j++;
}
if(i==n) puts("Yes");
else printf("No\n");
return 0;
}