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

发布了20 篇原创文章 · 获赞 0 · 访问量 515

猜你喜欢

转载自blog.csdn.net/weixin_45799835/article/details/104286931