C - Obtain The String 序列自动机

传送门:https://vjudge.net/contest/361562#problem/C

题意

  多组样例,给你一个串s和串t还有一个空串x,要求往x里添加s的子序列,使x变为t,求添加次数。

思路

  使用序列自动机狗仔串s的nxt数组,把整个t串进行匹配,当失配的时候,把前面已经匹配成功的部分当成一次子序列的添加,再从当前失配位置从头匹配,如果还是匹配失败则无法完成输出-1.

AC代码

#include<iostream>
#include<string.h>
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
int T,ans,flag;
char s[maxn],t[maxn];
int nxt[maxn][27];
void init(char *s){
    int len=strlen(s);
    for(int i=0;i<26;i++) nxt[len][i]=inf;
    for(int i=len-1;i>=0;i--){
        for(int j=0;j<26;j++){
            nxt[i][j]=nxt[i+1][j];
        }
        nxt[i][s[i]-‘a‘]=i+1;
    }
}
bool find(char *t){
    int len=strlen(t);
    int pos=-1;
    for(int i=0;i<len;i++){
        pos=nxt[pos+1][t[i]-‘a‘];
        if(pos==inf) return 0;
    }
    return 1;
}
int main()
{
    cin>>T;
    while(T    --){
        cin>>s>>t;
        ans=1;flag=1;
        init(s);
        int lent=strlen(t),pos=0;
        for(int i=0;i<lent;i++){
            int k=t[i]-‘a‘;
            if(nxt[pos][k]==inf){
                ans++;
                pos=0;
                if(nxt[pos][k]==inf){
                    flag=0;break;
                }
                pos=nxt[pos][k];
            }
            else{
                pos=nxt[pos][k];
            }
        }
        if(flag)
            cout<<ans<<‘\n‘;
        else
            cout<<-1<<‘\n‘;
    }
    return 0;
}

原文地址:https://www.cnblogs.com/qq2210446939/p/12690410.html

时间: 2024-08-30 14:45:31

C - Obtain The String 序列自动机的相关文章

杭电多校HDU 6586 String(序列自动机 贪心)题解

题意: 给你一个串,现需要你给出一个子序列,满足26个约束条件,\(len(A_i) >= L_i\) 且 \(len(a) <= R_i\), \(A_i\)为从a到z的26个字母. 思路: 先用序列自动机(?)构造出某个位置后每个字母的个数,每个字母 的第一个位置. 然后每次贪心地加入最小的字符,加入的条件为当前字母加入后,后面的字符满足剩余的条件. 即剩余的字母在不超R_i的情况下能构成k长度的串,剩余的字母\(A_i+\)已拿取字母\(A_i >= L_i\)且满足\(L_i\)

序列自动机

好像很高端的样子... 其实真的很简单... 序列自动机只有当数的类型比较少的时候才适用,一般出现字符串中,所以我们不妨设我们要处理的为字符串$A$ 然后我们只需要记住第$i$个位置后字母$j$最早出现的位置即可. 就是这么简单 时间复杂度$O(26N)$ 序列自动机的功能就是能遍历所有的子序列 好像非常冷门的样子...... #include<cstdio> #include<cstdlib> #include<iostream> #include<fstrea

BZOJ 4032 HEOI2015 最短不公共子串 后缀自动机+序列自动机+BFS

题目大意:给定字符串A和B,求A最短的子串/子序列S满足S不是B的子串/子序列 这题真TM有毒*2 搞法类似这道题 然后子串是后缀自动机 子序列自然就是序列自动机了= = 每更新一个x节点时所有没有x的后继的节点都连向这个节点 每个节点的parent是这个字母上一次出现的位置 每个字母记录最后一次出现的位置 更新指针时沿着parent指针撸一遍就行了 #include <cstdio> #include <cstring> #include <iostream> #in

Nowcoder contest 392 J (模板题)【序列自动机】

<题目链接> 题目大意:给你一个母串A,然后进行q次询问,每次询问给定一个长度不超过母串的字符串,问你这个字符串是否是母串的子串. 解题分析:序列自动机模板题.本题的思想就是考虑贪心的去匹配,我们希望当前匹配到的位置越靠前越好.所以对于母串每一位都记一下下一次出现某个字符的位置.匹配的时候从第零位(虚根)开始,如果能一直匹配下去就是$Yes$ ,否则就是 $No$,这些操作就是用序列自动机简单实现. 单次查询的复杂度是$O(|B_i|)$ 的,序列自动机预处理的复杂度是 $O(26|A|)$的

CF 1150 D Three Religions——序列自动机优化DP

题目:http://codeforces.com/contest/1150/problem/D 老是想着枚举当前在给定字符串的哪个位置,以此来转移. 所以想对三个串分别建 trie 树,然后求出三个trie树上各选一个点的答案.那么从“在三个trie树的根,在给定字符串的0位置”开始扩展. 当然 TLE 了. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #

序列自动机 浅谈

其实这个东西真的算自动机吗?好像还真的符合自动机的定义啊: 我将在下面用人话来定义序列自动机,并不像某度某科一样不说人话: 设一个字符集S,nxt[i][j]表示第i个位置往后第一个j元素出现的位置: 这个nxt数组可以O(n)的求出来,可以自行验证: for(int i=n-1;i>=0;--i){ for(int j=1;j<=26;++j) nxt[i][j]=nxt[i+1][j]; nxt[i][s[i+1]-'a'+1]=i+1; } 我们会发现一个神奇的事情:这是一个DAG! 她

浅谈序列自动机

简介 序列自动机是一个可以快速判断字符串\(t\)是否是字符串\(s\)的子串的一个算法. 构造 对\(s\)构造序列自动机,使用\(Nxt_{i,j}\)代表从第\(i\)个位置开始,字符\(j\)出现的第一个位置.我们倒着遍历更新即可. int nxt[N][27]; void init(char *s){ int l=strlen(s); for(int i=0;i<26;i++) nxt[l][i]=INF; for(int i=l-1;i>=0;i--){ for(int j=0;j

2019 Multi-University Training Contest 1 String(序列自动机+贪心)

题意:给你一个字符串 现在要你找出一个长度为k的字典序最小的子序列 且要求每个字母出现的个数要满足要求 思路:我们可以贪心构造每一位字符 优先放置字典序更小的字符 判断是否合法即可 #include <bits/stdc++.h> using namespace std; const double pi = acos(-1.0); const int N = 1e5+7; const int inf = 0x3f3f3f3f; const double eps = 1e-6; typedef

zoj 3228 Searching the String(AC自动机)

题目连接:zoj 3228 Searching the String 题目大意:给定一个字符串,然后现在有N次询问,每次有一个type和一个子串,问说子串在字符串中出现几次,type 为0时为可重叠,为1时为不可重叠. 解题思路:不过没有type=1的限制,那么就是普通的AC自动机匹配问题,对于不可重叠问题,可以对于每个节点记录 一下上一次匹配到的pos,用当前匹配的i减掉pos看有没有超过长度,有超过即为合法匹配,否则忽略. 题目中有很多相同的子串,一开始我用jump数组用类似链表的形式记录每