• 【AT3963】[AGC024F] Simple Subsequence Problem(子序列自动机上状压DP)


    点此看题面

    • 有一个(01)串集合(S),通过(n+1)(01)串给出:第(i)个串长度为(2^{i-1}),它的第(j)位表示(j-1)长度为(i-1)的二进制表示是否出现在(S)中。
    • 求一个最长的(01)串(多解则字典序最小),满足至少是(S)(k)个串的子序列。
    • (nle20)

    子序列自动机

    感觉这道题才是真正意义上的子序列自动机,和某模板题完全不是一个难度的。

    这里相当于是把序列的剩余部分看作节点,那么加上一个字符就是贪心找到剩下的序列中的第一个相同字符,将它连同之前的部分完全删去。

    容易发现任意串在子序列自动机中的匹配路径是唯一的(其实是自动机的通用性质)。

    而这个性质的存在就意味着我们不会算重或是算漏情况。

    状压(DP)

    考虑我们记录两个串(A,B)(A)表示当前已经完成匹配的子序列,(B)表示匹配剩下的序列。

    因为只要知道匹配剩下的序列是什么就与原序列是谁无关了,转移的路径相同,因此只要为所有串设好初始状态,然后就可以一起转移了。

    转移分为三种:直接放弃转移让(A)成为最终子序列;找到(B)中第一个(0)转移;找到(B)中的第一个(1)转移。

    关于(B)中的第一个(0/1),我们可以事先预处理,只要考虑最高位是否为(0/1),如果是则第一个就是最高位,否则就是除去最高位剩余部分的第一个(0/1),显然这已经在先前求出。(其实这就是一个建子序列自动机的过程)

    具体实现中,因为(|A|+|B|le n),可以使用状压(DP),把两个串接在一起记录一下分割线即可。

    由于这道题我们需要知道是否存在前导(0),不妨强行在(A)的最前面添上一个(1),则(1)之后到分割线的部分就是真正的(A)了。

    代码:(O(n2^n))

    #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 20
    using namespace std;
    int n,k,f[N+5][1<<N+1],S0[N+5][1<<N],S1[N+5][1<<N];char s[N+5][(1<<N)+5];
    int main()
    {
    	RI i,j,l;for(scanf("%d%d",&n,&k),i=0;i<=n;++i) if(scanf("%s",s[i]),i) for(j=0,l=1<<i;j^l;++j)
    		s[i][j]&1&&(f[i][j|l]=1),S0[i][j]=j>>i-1&1?S0[i-1][j^(1<<i-1)]:i,S1[i][j]=j>>i-1&1?i:S1[i-1][j];//设上初始状态;预处理长度为i的j第一个0/1位置
    	RI t,A,B;for(l=1<<n+1,i=n;i;--i) for(j=0;j^l;++j) A=j>>i,B=j&((1<<i)-1),f[0][A]+=f[i][j],//解压出A,B;放弃转移作为最终串
    		(t=S0[i][B])&&(f[t-1][A<<t|(B&((1<<t-1)-1))]+=f[i][j]),(t=S1[i][B])&&(f[t-1][A<<t|(1<<t-1)|(B&((1<<t-1)-1))]+=f[i][j]);//与第一个0匹配;与第一个1匹配
    	for(i=n;i;--i) for(l=1<<i,j=0;j^l;++j) if(f[0][1<<i|j]>=k) {for(--i;~i;--i) putchar(48|(j>>i&1));return 0;}return 0;//先枚举长度,然后尽可能小
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    安卓AlertDialog的使用
    蚂蚁的腿
    年龄排序
    Digital Roots
    小明的存钱计划
    不高兴的小明
    管闲事的小明
    小明的调查作业
    爱摘苹果的小明
    小明的难题
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/AT3963.html
Copyright © 2020-2023  润新知