CodeForces - 1295C Obtain The String(二分 / 序列自动机)


传送门:CodeForces - 1295C

题目描述

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:

  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.

输入描述

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|≤105)$ consisting of lowercase Latin letters.

The second line of each testcase contains one string $t$ $(1≤|t|≤105)$ consisting of lowercase Latin letters.

输出描述

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

思路分析

给你两个串s和t,问最小需要几个s中的子序列可以组成t。
有种做法。
一是序列自动机:

  • 预处理出nex[i][j]数组,表示i之后第一次出现j的位置。
  • 然后暴力匹配就行了。

二是二分查找:

  • 将26个字母的位置存进26个数组中。
  • 位置肯定是有序的,所以可以二分。
  • 也是暴力匹配就行了。

样例输入

3
aabce
ace
abacaba
aax
ty
yyt

样例输出

1
-1
3

二分代码

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <iomanip>
#if __cplusplus >= 201103L
#include <unordered_map>
#include <unordered_set>
#endif
#define ls ro<<1
#define fi first
#define se second
#define rs ro<<1|1
#define ll long long
#define pb push_back
#define vi vector<int>
#define lowbit(x) x&(-x)
#define pii pair<int,int>
#define lson ro<<1,l,mid
#define umap unordered_map
#define uset unordered_set
#define rson ro<<1|1,mid+1,r
#define all(x) x.begin(),x.end()
#define mem(a,b) memset(a,b,sizeof(a))
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);cout.tie(0);

using namespace std;

const int INF = 0x3f3f3f3f;
const int N=1e5+10;

char s[N],t[N];


int main() {

#ifdef xiaofan
    freopen("in.txt","r",stdin);
#endif

    int T;
    cin>>T;
    while(T--) {
        int vis[26]= {0};
        vector<int>q[26];
        scanf("%s%s",s,t);
        int n=strlen(s),m=strlen(t);
        
        for(int i=0; i<m; i++) {
            vis[t[i]-'a']=1;
        }
        for(int i=0; i<n; i++) {
            vis[s[i]-'a']=0;
            q[s[i]-'a'].pb(i);
        }
        
        int f=0;
        for(int i=0; i<26; i++) {
            if(vis[i]==1) {
                f=1;
                break;
            }
        }
        if(f) {
            puts("-1");
            continue;
        }
        int ans=1,p=0,idx=-1;
        while(p!=m) {
            
            int x=t[p]-'a';
            int nx=upper_bound(q[x].begin(),q[x].end(),idx)-q[x].begin();
            if(nx==q[x].size()){
                ans++;
                idx=-1;
            }else{
                p++;
                idx=q[x][nx];
            }
        }
        cout<<ans<<endl;
    }




    return 0;
}

序列自动机代码

#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <iomanip>
#if __cplusplus >= 201103L
#include <unordered_map>
#include <unordered_set>
#endif
#define ls ro<<1
#define fi first
#define se second
#define rs ro<<1|1
#define ll long long
#define pb push_back
#define vi vector<int>
#define lowbit(x) x&(-x)
#define pii pair<int,int>
#define lson ro<<1,l,mid
#define umap unordered_map
#define uset unordered_set
#define rson ro<<1|1,mid+1,r
#define all(x) x.begin(),x.end()
#define mem(a,b) memset(a,b,sizeof(a))
#define IOS ios_base::sync_with_stdio(0); cin.tie(0);cout.tie(0);

using namespace std;

const int INF = 0x3f3f3f3f;
const int N=1e5+10;

char s[N],t[N];
int nex[N][26];


int main() {

#ifdef xiaofan
    freopen("in.txt","r",stdin);
#endif

    int T;
    cin>>T;
    while(T--) {
        int vis[26]= {0};
        scanf("%s%s",s+1,t+1);
        int n=strlen(s+1),m=strlen(t+1);
        for(int i=1; i<=m; i++)
            vis[t[i]-'a']=1;
        for(int i=1; i<=n; i++)
            vis[s[i]-'a']=0;
        int f=0;
        for(int i=0; i<26; i++) {
            if(vis[i]==1) {
                f=1;
                break;
            }
        }
        if(f) {
            puts("-1");
            continue;
        }
        for(int i=0; i<26; i++)
            nex[n][i]=0;
        for(int i=n; i>=1; i--) {
            for(int j=0; j<26; j++) {
                nex[i-1][j]=nex[i][j];
            }
            nex[i-1][s[i]-'a']=i;
        }
        int ans=1,pos=0;
        for(int i=1; i<=m; i++) {
            pos=nex[pos][t[i]-'a'];
            if(!pos) {
                ans++;
                i--;
                pos=0;
            }

        }
        cout<<ans<<endl;
    }



    return 0;
}
&nbsp;

文章作者: 小凡
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小凡 !
评论
  目录
隐藏
{% if theme.sakura.enable %}{% endif %}