当前位置: 代码迷 >> 综合 >> CF 1295——C.Obtain The String【二分】
  详细解决方案

CF 1295——C.Obtain The String【二分】

热度:19   发布时间:2023-12-16 22:54:26.0

题目传送门


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 = a c , s = a b c d e z=ac, s=abcde z=ac,s=abcde, you may turn z into following strings in one operation:

z = a c a c e z=acace z=acace (if we choose subsequence ace);
z = a c b c d z=acbcd z=acbcd (if we choose subsequence bcd);
z = a c b c e z=acbce 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 ) T (1≤T≤100) T(1T100) — the number of test cases.

The first line of each testcase contains one string s ( 1 ≤ ∣ s ∣ ≤ 1 0 5 ) s (1≤|s|≤10^5) s(1s105) consisting of lowercase Latin letters.

The second line of each testcase contains one string t ( 1 ≤ ∣ t ∣ ≤ 1 0 5 ) t (1≤|t|≤10^5) t(1t105) 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 ? 1 0 5 2 *10^5 2?105.


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.


input

3
aabce
ace
abacaba
aax
ty
yyt


output

1
-1
3


题意

  • 给定两个字符串s和t,你有一个空字符串z

  • 每次可以取s的任意一个子序列加到z后面

  • 问至少要取多少次才能让z等价于t


题解

  • vector存s中26个字母的位置

    然后字符串 t t t从前往后一个个查找

    用变量p记录查到上一个字符时在字符串s中的位置(初始化为-1)

    如果在t内碰到一个字符,没有在s中出现过,输出-1结束当次程序

    否则,看当前的p是否大于等于这个字符在s中出现的最后一个位置

    如果是,说明这一次子序列已经不能往后面取了,说明得另起一次从头取子序列

    ans++,让p等于当前字符在s中出现的第一个位置

    如果不是二分找大于p的第一个这个字符的位置,让p等于这个位置即可

  • 注意,ans初始化为1,vector要清空……

    思路用到了一点点贪心,就是每次都是取上一次的位置后出现的第一个指定字符的位置

    反正正常模拟肯定超时要二分优化,嗯!


AC-Code

#include <bits/stdc++.h>
using namespace std;vector<int>vec[26];
int num[26];
int main() {
    int T;cin >> T;while (T--) {
    memset(num, 0, sizeof num);for (int i = 0; i < 26; ++i)vec[i].clear();string s, t;cin >> s >> t;for (int i = 0; i < s.length(); ++i) {
    vec[s[i] - 'a'].push_back(i);++num[s[i] - 'a'];}int ans = 1;int p = -1;for (int i = 0; i < t.length(); ++i) {
    if (!num[t[i] - 'a']) {
    ans = -1;break;}else if (p >= vec[t[i] - 'a'][num[t[i] - 'a'] - 1]) {
    ++ans;p = vec[t[i] - 'a'][0];}else p = vec[t[i] - 'a'][upper_bound(vec[t[i] - 'a'].begin(), vec[t[i] - 'a'].end(), p) - vec[t[i] - 'a'].begin()];}cout << ans << endl;}return 0;
}
  相关解决方案