Bootstrap

字符串的子序列

给定两个只包含小写字母的字符串,分别为st

现在将字符串s进行无限次拼接得到s′,问字符串t是否是s′的一个子序列。

如果是,输出s′中的最后一个位置;否则输出-1。

输入格式

输入两行,每行为一个只包含小写字母的字符串。

输出格式

输出一个整数。

测试样例一
rainsure
rraaiinn
36
测试样例二
abcdefg
bcdk
-1

思路:
开26个桶(这里的桶即set) ,将s字符串中字符的下标索引放入桶中;遍历t字符串,如果该字符对应的桶不为空,找比上一个位置严格大的(也就是保证能在s字符串中从上一个位置一直往后找),如果往后找到最后了还是没有,则往后拼接一个s,cnt++,(其实就是再重新到s的开头往后继续进行查找),最后t遍历完了,代表子序列匹配完成 ,输出cnt个完整的s的长度+最后一个位置下标索引+1即为所求。如果在中间遍历t的过程中,遇到该字符对应的桶是空的,就输出-1。

一开始做超时真的讨厌,后来又答案错误更是讨厌。

正确解法:外层字符串遍历时间复杂度为m,内层利用upper_bound二分查找时间复杂度为logn
总得大概为mlogn,更优化一点

关于lower_bound( )和upper_bound( )的常见用法

AC:

#include <bits/stdc++.h>

using namespace std;

set<int> p[26];
int lastp=-1,cnt;

int main()
{
    string s,t;
    cin>>s>>t;
    for(int i=0;i<s.length();i++) p[s[i]-'a'].insert(i);
    for(int i=0;i<t.length();i++)
    {
        int key=t[i]-'a';
        if(p[key].size())
        {
            auto it=p[key].upper_bound(lastp);
            if(it==p[key].end())
            {
                cnt++;
                it=p[key].begin();
            }
            if(i==t.length()-1)
            {
                cout<<cnt*s.length()+(*it)+1<<endl;
                return 0;
            }
            lastp=*it;
        }
        else
        {
            cout<<"-1"<<endl;
            return 0;
        }
    }
}

WA:

#include<bits/stdc++.h>
using namespace std;
//运行超时
bool isSubsequence(string s, string t) {
        int n = s.length(), m = t.length();
        int i = 0, j = 0;
        while (i < n && j < m) {
            if (s[i] == t[j]) {
                i++;
            }
            j++;
        }
        return i == n;
    }

int main(){
    cin.tie(0);cout.tie(0);
    ios::sync_with_stdio(false);
    string s,t;
    cin>>s>>t;
    string sum=s;
    int flag=0,flag1=0;
    int id;
    for(int i=0;i<t.size();i++)
    {

    }
    for(int i=1;;i++){
        id=i;
        if(isSubsequence(t,sum))
        {
            flag=1;
            break;
        }
        sum+=s;
    }
   // cout<<id<<" "<<s.size()<<endl;
    int num;
   for(int i=sum.size()-1;i>=0;i--)
   {
       if(sum[i]==t[t.size()-1])
       {
           num=sum.size()-i-1;
           break;
       }
   }
   //cout<<num<<endl;
   cout<<id*s.size()-num;

}
//答案错误
bool isSubsequence(string s, string t) {
        int n = s.length(), m = t.length();
        int i = 0, j = 0;
        while (i < n && j < m) {
            if (s[i] == t[j]) {
                i++;
            }
            j++;
        }
        return i == n;
}
int main()
{
    cin.tie(0);cout.tie(0);
    ios::sync_with_stdio(false);
    string s, t,str;
    cin >> s >> t;
    int j = 0;
    int cnt = 1;
    int num=0;
    vector<char> a,b;
    for(int i=0;i<t.size();i++)
    {
        a.push_back(t[i]);
    }
    vector<char>::iterator it1;
    for(auto it=++a.begin();it!=a.end();)
    {
        it1=find(a.begin(),it,*it);
        if(it1!=it)
            it=a.erase(it);
        else
            it++;
    }
    for(auto it=a.begin();it!=a.end();it++)
        str+=*it;
    if(!isSubsequence(str,s))
    {
        cout<<"-1";
        return 0;
    }
    for(int i = 0; i < t.size(); i++)
    {
        while(t[i] != s[j])
        {
            if(j == s.size() - 1)
            {
                cnt++;
                j = -1;
            }
            j++;
            num++;
        }
        j++;
        num++;
        continue;

    }
        cout<<num;

}

悦读

道可道,非常道;名可名,非常名。 无名,天地之始,有名,万物之母。 故常无欲,以观其妙,常有欲,以观其徼。 此两者,同出而异名,同谓之玄,玄之又玄,众妙之门。

;