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;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    Visual Studio 快捷键
    C#编程使用Managed Wifi API连接无线SSID
    C#两种创建快捷方式的方法
    COJ 1059
    [Unity3D]Unity3D游戏开发之鼠标滚轮实现放大缩小
    cloudstack4.4新增功能前瞻
    hdu 4635 Strongly connected (tarjan)
    freemarker声明变量
    Android 4.4 Kitkat Phone工作流程浅析(六)__InCallActivity显示更新流程
    评教,路上的风景更美
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/SubSeqAutomation.html
Copyright © 2011-2022 走看看