Obtain The String

题目连接: Obtain The String

题目:

You are given two strings s and t consisting of lowercase Latin letters. Also you have a string z which is initially empty. You want string z to be equal to string t. You can perform the following operation to achieve this: append any subsequence of s at the end of string z. A subsequence is a sequence that can be derived from the given sequence by deleting zero or more elements without changing the order of the remaining elements. For example, if z=ac, s=abcde, you may turn z into following strings in one operation:

z=acace (if we choose subsequence ace);
z=acbcd (if we choose subsequence bcd);
z=acbce (if we choose subsequence bce).
Note that after this operation string s doesn’t change.

Calculate the minimum number of such operations to turn string z into string t.

Input
The first line contains the integer T (1≤T≤100) — the number of test cases.
The first line of each testcase contains one string s (1≤|s|≤10^5) consisting of lowercase Latin letters.
The second line of each testcase contains one string t (1≤|t|≤10^5) consisting of lowercase Latin letters.
It is guaranteed that the total length of all strings s and t in the input does not exceed 2⋅10^5.

Output
For each testcase, print one integer — the minimum number of operations to turn string z into string t. If it’s impossible print −1.

Example
Input
3
aabce
ace
abacaba
aax
ty
yyt
Output
1
-1
3

大致题意: 给你2个字符串s, t. 你在s串中选取字符后在空串z中组合出t串. 规则是每一次在s串选择一个字符后, 再选只能选该字符后面的字符, 不能选择前面的, 且选取后顺序不能改变. 问你最少要经过多少次选取才能把z变成t. 如果不能则输出-1.

解题思路:

我们可以把s串中每一种字母出现的位置进行记录, 当需要该字母的时候看看该字母有没有符合要求的位置, 如果有则选取符合要求的最小下标. 反之则开始新的一次选取. 如果需要选取s中没有的字符, 则输出-1.
在找查下标时, 由于数据量比较大, 需要采用二分找查.

AC代码:

#include <bits/stdc++.h>
#define ll long long
using namespace std;
vector<int> v[26]; //由于不知道26个字母的个数, 推荐使用动态数组.
int main()
{
	int T; cin >> T;
	while (T--) {
		string s, t; cin >> s >> t;
		for (int i = 0; i < 26; i++) v[i].clear(); //不要使用memset清空, 可能会出问题.
		for (int i = 0; i < s.size(); i++) v[s[i] - 'a'].push_back(i);
		int ans = 1; //由于保证t非空, 所以至少操作1次
		int k = -1; //由于每次的首次选取可以任选, 所以可设为-1
		for (int i = 0; i < t.size(); i++) {
			int x = t[i] - 'a';
			if (v[x].empty()) { ans = -1; break; } //t中出现了s中没有的字符

			int index = upper_bound(v[x].begin(), v[x].end(), k) - v[x].begin();
			if (index == v[x].size()) { k = -1, ans++, i--; } //说明没找到
			else k = v[x][index];
		}
		cout << ans << endl;
		
		// 你也可以考虑用 lower_bound() 皮一下
		/* int ans = 1, k = 0; //这时候k就可以从0开始了
		for (int i = 0; i < t.size(); i++) {
			int x = t[i] - 'a';
			if (v[x].empty()) { ans = -1; break; }

			int index = lower_bound(v[x].begin(), v[x].end(), k) - v[x].begin();
			if (index == v[x].size()) { k = 0, ans++, i--; }
			else k = v[x][index] + 1;
		}
		cout << ans << endl; */
	}
	return 0;
}

这个题主要考察lower_bound() 和 upper_bound() 两个函数以及vector动态数组的妙用.

END

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

逍遥Fau

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值