解题报告 CodeForces - 1295C 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 zz into following strings in one operation:

  1. z=acace (if we choose subsequence ace);
  2. z=acbcd (if we choose subsequence bcd);
  3. 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\leq T\leq 100) — the number of test cases.

The first line of each testcase contains one string s (1\leq |s|\leq 10^{5}) consisting of lowercase Latin letters.

The second line of each testcase contains one string t (1\leq |t|\leq 10^{5}) consisting of lowercase Latin letters.

It is guaranteed that the total length of all strings ss and tt in the input does not exceed 2\cdot 10^{5}.

Output

For each testcase, print one integer — the minimum number of operations to turn string zz into string tt. If it's impossible print −1.

Example

Input

3
aabce
ace
abacaba
aax
ty
yyt

Output

1
-1
3

题意:

给定两个字符串 s 和 t ,字符串 z 开始为空字符串,每次操作可以在 s 中选一个子序列(区别于子串)拼接在 z 后边,最终将z变为 t 

输入: T 组样例,每组样例有两行,第一行为字符串 s ,第二行为字符串 t

输出:空字符串 z 变为 t 的最小步数

思路:

1.看到这道题我想起了dp的经典题目拦截导弹,于是自然而然的往dp的方向想了。(其实和拦截导弹没啥关系)

2.dp[i][j]表示位置 i 及之后 j 最近一次出现的位置,如果恰好出现在位置 i 上则dp[i][j] = i ;否则dp[i][j] = dp[i+1][j]

3.按照字符串 t 中字母的顺序逐个查找,pos指字符串 s 中选择序列的位置,开始从 s 的第一位即下标为0的位置开始查找,如果某个序列可以一次选中,则将pos移向 s 串中该字母最近一次出现的位置也就是刚刚处理好的dp数组;否则ans++进行下一次的序列选择,pos移动回0

 

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define maxn 100005
#define mod 998244353
int ca,dp[maxn][35];
string s,t;

int main()
{
    cin>>ca;
    while(ca--)
    {
        cin>>s>>t;
        int ls=s.length();
        int lt=t.length();
        for(int i=0;i<26;i++)
        {
            dp[ls][i]=inf;
        }
        for(int i=ls-1;i>=0;i--)
        {
            for(int j=0;j<26;j++)
            {
                if(s[i]-'a'==j)dp[i][j]=i;
                else dp[i][j]=dp[i+1][j];
            }
        }
        int pos=0,ans=1;
		for(int i=0;i<lt;i++)
        {
            int tmp=t[i]-'a';
            if(dp[0][tmp]==inf)
            {
                ans=-1;
                break;
            }
            if(dp[pos][tmp]==inf)
            {
                pos=0;
                ans++;
            }
            pos=dp[pos][tmp]+1;
        }
        cout<<ans<<endl;
    }
    return 0;
}

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值