zoukankan      html  css  js  c++  java
  • 【洛谷5826】【模板】子序列自动机

    点此看题面

    • 给定一个长度为(n)的文本串,字符集大小为(m)
    • (q)次询问,每次给定一个字符串,询问是否为文本串的一个子序列。
    • (n,m,qle10^5)

    思想核心:贪心

    其实就这题而论,子序列自动机是一个非常简单易懂的算法,闲得无聊来水一水。

    核心思想是贪心,就是考虑我们每次找到尽可能近的字符匹配一定是最优的。

    方法一:主席树

    由于常见字符串问题的字符集大小是(26),所以相信大家都写过一个东西,就是记录(S_{i,c})表示第(i)位之后第一个字符(c)所在位置。

    要维护这个只需从后往前枚举,每次(S_i)继承(S_{i+1}),并更新(S_{i,a_{i+1}}=i+1)

    这题字符集很大,考虑继承操作就相当于是一个版本的赋值,随后我们进行的是在新版本上的一个单点修改。

    发现这就是一个用主席树实现可持久化数组的过程,非常板子。

    方法二:(vector)+二分

    直接对于每个字符集开一个(vector),要找到第(i)位之后第一个字符(c),只要在字符(c)对应的(vector)中求出(upper\_bound(i))即可。

    而且把(vector)换成(set)甚至能实现带修,这是主席树做不到的。所以说主席树直接被全方位吊打。

    代码:(O(nlogn))

    当然是方法二啦,不会真的有人会去写主席树吧。

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    using namespace std;
    int n,m;vector<int> S[N+5];vector<int>::iterator it;
    int main()
    {
    	RI Qt,i,x,y;for(scanf("%d%d%d%d",&x,&n,&Qt,&m),i=1;i<=n;++i) scanf("%d",&x),S[x].emplace_back(i);//对每种字符维护个vector
    	RI t;W(Qt--) {for(scanf("%d",&t),x=0;t;--t) scanf("%d",&y),
    		~x&&(x=(it=upper_bound(S[y].begin(),S[y].end(),x))==S[y].end()?-1:*it);puts(~x?"Yes":"No");}//利用upper_bound查找下一位
    	return 0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    Python学习摘要201802
    机器学习-梯度下降参数调优小结
    用尽洪荒之力学习Flask源码
    Flask类的属性和方法大全
    Flask第三方工具组件介绍
    Flask自带的常用组件介绍
    Centos下部署Flask
    Python Tips阅读摘要
    web程序设计关于我们
    软工实践总结
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/SubSeqAutomation.html
Copyright © 2011-2022 走看看