hiho227 Longest Subsequence

目錄

題目1 : Longest Subsequence

題目分析:

1.題是什麼?

2.思路

  (1).我的思路:

  (2).官方思路

3.ac代碼

(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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章