目錄
(1).我的方法(時間複雜度1000000+100000*20(對1000000做二分最多20次),空間複雜度100000)
(2).官方方法(時間複雜度1000000*26+100000,空間複雜度26*1000000)
題目1 : Longest Subsequence
時間限制:10000ms
單點時限:1000ms
內存限制:256MB
描述
You are given a set of N words W1, W2, ... WN and a target string S. Find the longest word which is also a subsequence of S.
輸入
The first line contains an integer N. (1 <= N <= 10000)
The following N lines each contain a word Wi. (1 <= Σ|Wi| <= 100000)
The last line contains the string S. (1 <= |S| <= 100000)
輸出
The length of the longest word which is also a subsequence of S.
樣例輸入
3
a
ac
abc
acbc
樣例輸出
3
題目分析:
1.題是什麼?
給你n個字符串(n最大10000),總長度不會大於100000;再給你一個目標字符串target(長度1000000),問你這n個字符串中是target的子序列的最長的串長度是多少?
2.思路
(1).我的思路:
既然我們只是要尋找最長的滿足是子序列的a串,也許我們只需要挨個判斷當前a串是否是目標b串的子序列,最後比較留下最大的就好,單純的通過跑目標b串得知某個字符串是否是子序列最壞情況需要|b|=1000000,10000個就是一百億,不行,
由於已知當前串總長度也不過100000,故而多數a串都是短串,我們大可基於a串去比較,我的方法就是通過預處理b串中每種字符的位置有序存於vector,通過二分查找是否存在位置合適的某字符,去判斷是否子序列.
(2).官方思路
通過預處理目標串得知每個位置後方第一個字符a,第一個字符b,第一個字符c,....的位置,這樣可以直接遍歷a串的同時進行跳錶來判斷是否是子序列,斷開了就不是.
3.ac代碼
(1).我的方法(時間複雜度1000000+100000*20(對1000000做二分最多20次),空間複雜度100000)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=10001;
const int maxascii=256;//全字符集映射於vector
string s[maxn];
string target;
vector<int> v[maxascii+1];
vector<int>::iterator ite;
void solve(){
std::ios::sync_with_stdio(false);
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>s[i];
cin>>target;
for(int i=0;target[i];i++){
v[target[i]].push_back(i);
}
int ans=0;
for(int i=0;i<n;i++){
int pos=-1,len;//pos記錄當前匹配的位置,len記錄字符串長度
for(len=0;s[i][len];len++){
int temp=s[i][len];
//通過二分查找大於上一個字符的匹配位置的當前字符位置
ite=upper_bound(v[temp].begin(),v[temp].end(),pos);
//目標串中找到了則迭代pos,繼續,否則退出循環
if(ite!=v[temp].end()) pos=*ite;
else break;
}
//全部匹配才迭代ans
if(!s[i][len]) ans=max(ans,len);
}
cout<<ans<<endl;
}
int main(){
solve();
return 0;
}
(2).官方方法(時間複雜度1000000*26+100000,空間複雜度26*1000000)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn=10001;
const int maxascii=26;
const int maxtargetlen=1000001;
string s[maxn];
string target;
int nextchar[maxtargetlen][maxascii];
void solve(){
std::ios::sync_with_stdio(false);
int n;
cin>>n;
for(int i=0;i<n;i++) cin>>s[i];
cin>>target;
int targetlen=target.length();
for(int i=0;i<maxascii;i++) nextchar[targetlen][i]=0;
for(int i=targetlen;i>=0;i--){
for(int j=0;j<maxascii;j++) nextchar[i][j]=nextchar[i+1][j];
nextchar[i][target[i]-'a']=i+1;
}
int ans=0;
for(int i=0;i<n;i++){
int temp=0,len;
for(len=0;s[i][len];len++){
temp=nextchar[temp][s[i][len]-'a'];
if(!temp) break;
}
if(!s[i][len]) ans=max(ans,len);
}
cout<<ans<<endl;
}
int main(){
solve();
return 0;
}