• Codeforces 1295C


    题目大意:

    给定两个字符串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
    ";
                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<<'
    ';
    }
    int main(){
        ios::sync_with_stdio(0);
        cin.tie(0);cout.tie(0);
        int T;cin>>T;while(T--)
            solve();
        
        return 0;
    }
  • 相关阅读:
    获得微软最具影响力开发者(GDI)
    推荐一个制作卡通头像的网站(超强)
    李煜词全集
    15款语言学习2.0网络服务
    SNS社么时候回归社交? !!
    公司附近雪景
    Powershell实践之Discuz!NT自动打包发布
    使用 Office Live 时 Install Office Live Update 1.2出错的解决办法
    修改linux swap空间的swappiness,降低对硬盘的缓存
    TFS "TF30063: 您没有权限访问 MicrosoftIIS/7.0."
  • 原文地址:https://www.cnblogs.com/stelayuri/p/12241989.html
Copyright © 2020-2023  润新知