1. 程式人生 > >newcoder 練習賽17 B 好位置 dp 最長公共子序列

newcoder 練習賽17 B 好位置 dp 最長公共子序列

abc i++ 包含 輸入 http light DC 同時 輸出

鏈接: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=kj成立。
問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;
} 

  

newcoder 練習賽17 B 好位置 dp 最長公共子序列