给定两个只包含小写字母的字符串,分别为s和t。
现在将字符串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;
}