【Educational Codeforces Round 81 (Rated for Div. 2) C】Obtain The String
【题解】
显然我们得按顺序获得目标t的每个字符。 对于t[0],t[1],t[2],t[3]... 我们可以在s中找到这么一个子序列。 显然如果找到尾巴还是没有需要的t[i]。 就得从s[0]开始重新开始顺序找。 (然后答案递增,因为表示要重新开始加一个子序列了) 但是如果这么直接找的话,复杂度是O(|s|*|t|)的 是无法接受的。 所以我们可以另外开一个数组 next[i][j] 表示在i-1位置,如果要找下一个紧接着的j的话,需要到哪个位置找。(这个next数组整体往左偏移了下,便于处理,因为不能包括本身,它的含义是不包括自己的下一个) 这个数组能在O(26*|s|)的时间复杂度内处理出来。 这样,在遍历t的每个字符的时候,就能在O(1)的时间内找到t[i]在s中的位置了。 所以算答案的时候复杂度是O(|t|)级别。【代码】
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N = 1e5;
int n,x;
string s;
string t;
int _next[N+10][30];
int main(){
#ifdef LOCAL_DEFINE
freopen("E:\\rush.txt","r",stdin);
#endif // LOCAL_DEFINE
ios::sync_with_stdio(0),cin.tie(0);
int T;
cin >> T;
while (T--){
cin >> s;
cin >> t;
int len = s.size();
for (int i = 0;i<26;i++) _next[len][i] = -1;
for (int i = len-1;i>=0;i--){
for (int j = 0;j < 26;j++) _next[i][j] = _next[i+1][j];
int key = s[i]-'a';
_next[i][key] = i+1;
}
//cout<<_next[0][0]<<endl;
len = t.size();
int ans = 1;
int cur = 0;
bool ok = true;
for (int i = 0;i < len;i++){
int kk = t[i]-'a';
if (_next[cur][kk]!=-1){
cur = _next[cur][kk];
}else{
ans++;
cur = 0;
if (_next[0][kk]==-1){
ok = false;
break;
}
cur = _next[cur][kk];
}
//cout<<cur<<endl;
}
if (!ok) cout<<-1<<endl;else
cout<<ans<<endl;
}
return 0;
}