newcoder 练习赛17 B 好位置 dp 最长公共子序列

链接:https://www.nowcoder.com/acm/contest/109/B
来源:牛客网

好位置
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 32768K,其他语言65536K
64bit IO Format: %lld

题目描述

给出两个串s和x
定义s中的某一位i为好的位置,当且仅当存在s的子序列 满足y=x且存在j使得i=k j成立。
问s中是否所有的位置都是好的位置。

输入描述:

一行两个字符串s,x,这两个串均由小写字母构成。
1 <= |s|, |x| <= 200000

输出描述:

Yes表示是。
No表示不是。
示例1

输入

abab
ab

输出

Yes
示例2

输入

abacaba
aba

输出

No
示例3

输入

abc
ba

输出

No


思路:dp[i]代表s前i个字符(包含第i个字符)所能匹配到e的最长位置
注意递推方程:如果s[i]==e[j] dp[i]=j;
       else dp[i]等于用该位置去替代(1,j)中最大的那一个字符与s[i]相等的位置,同时保证了最长公共序列
相当于在s的子序列里查找e串 ,66666666
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int dp[N][2];
string a,b;
vector<int>pos[26]; 
int main(){
	std::ios::sync_with_stdio(false);
	while(cin>>a>>b){
		int l1=a.size(),l2=b.size();
		for(int i=0;i<l2;i++) pos[b[i]-'a'].push_back(i);
		int j=0;
		for(int i=0;i<l1;i++){
			if(a[i]==b[j]) j++;
			else{
				int t=a[i]-'a';
				int tt=lower_bound(pos[t].begin(),pos[t].end(),j)-pos[t].begin()-1;
				j=tt+1;
			}
			dp[i][0]=j;
		}
		j=0;
		reverse(a.begin(),a.end());
		reverse(b.begin(),b.end());
		for(int i=0;i<=25;i++) pos[i].clear();
		for(int i=0;i<l2;i++) pos[b[i]-'a'].push_back(i);
		for(int i=0;i<l1;i++){
			if(a[i]==b[j]) j++;
			else{
				int t=a[i]-'a';
				int tt=lower_bound(pos[t].begin(),pos[t].end(),j)-pos[t].begin()-1;
				j=tt+1;
			}
			dp[i][1]=j;
		}
		int flag=1;
		for(int i=0;i<l1;i++){
			if(dp[i][0]+dp[l1-1-i][1]<l2) {flag=0;break;}
		}
		if(flag) cout<<"Yes"<<"\n";
		else cout<<"No"<<"\n";
	}
	return 0;
} 

  

猜你喜欢

转载自www.cnblogs.com/vainglory/p/9021568.html
今日推荐