Codeforces 1295C - Obtain The String


題目大意:

給定兩個字符串s和t,你有一個空字符串z

每次可以取s的任意一個子序列加到z后面

問至少要取多少次才能讓z等價於t

 

解題思路:

vector存s中26個字母的位置

然后t字符串從前往后一個個查找

用變量p記錄查到上一個字符時在字符串s中的位置(初始化為-1)

如果在t內碰到一個字符,沒有在s中出現過,輸出-1結束當次程序

否則,看當前的p是否大於等於這個字符在s中出現的最后一個位置

如果是,說明這一次子序列已經不能往后面取了,說明得另起一次從頭取子序列

ans++,讓p等於當前字符在s中出現的第一個位置

如果不是二分找大於p的第一個這個字符的位置,讓p等於這個位置即可

 

注意,ans初始化為1,vector要清空……

思路用到了一點點貪心,就是每次都是取上一次的位置后出現的第一個指定字符的位置

 

#include<bits/stdc++.h>
using namespace std;
string s,t;
vector<int> v[26];
int siz[26];
inline int gid(char s){
    return s-'a';
}
void solve(){
    cin>>s>>t;
    memset(siz,0,sizeof siz);
    int lens=s.size(),lent=t.size(),i,j,d,p=-1,pd,ans=1;
    for(i=0;i<26;i++)
        v[i].clear();
    for(i=0;i<lens;i++){
        d=gid(s[i]);
        v[d].emplace_back(i);
        siz[d]++;
    }
    for(i=0;i<lent;i++){
        d=gid(t[i]);
        if(siz[d]==0){//這個字符沒有出現過
            cout<<"-1\n";
            return;
        }
        if(p>=v[d][siz[d]-1]){//如果已經沒法在剩下的位置中取這個字符了,得另起一次從頭開始取子序列
            ans++;
            p=v[d][0];
        }
        else{//否則,二分找大於p的第一個這個字符的位置
            pd=upper_bound(v[d].begin(),v[d].end(),p)-v[d].begin();
            p=v[d][pd];
        }
    }
    cout<<ans<<'\n';
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;cin>>T;while(T--)
        solve();
    
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM