newcoder 練習賽17 B 好位置 dp 最長公共子序列
阿新 • • 發佈:2018-05-10
abc i++ 包含 輸入 http light DC 同時 輸出
空間限制:C/C++ 32768K,其他語言65536K
64bit IO Format: %lld
定義s中的某一位i為好的位置,當且僅當存在s的子序列 滿足y=x且存在j使得i=kj成立。
問s中是否所有的位置都是好的位置。
鏈接:https://www.nowcoder.com/acm/contest/109/B
來源:牛客網
空間限制: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表示是。示例1
No表示不是。
輸入
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 最長公共子序列