zoukankan      html  css  js  c++  java
  • 【BZOJ】4032: [HEOI2015]最短不公共子串(LibreOJ #2123)

    【题意】给两个小写字母串A,B,请你计算:

    (1) A的一个最短的子串,它不是B的子串

    (2) A的一个最短的子串,它不是B的子序列

    (3) A的一个最短的子序列,它不是B的子串

    (4) A的一个最短的子序列,它不是B的子序列

    不存在输出-1,1<=len(A),len(B)<=2000。

    【算法】后缀自动机+序列自动机

    【题解】虽然网上题解很多,但我总觉得这四个问题其实可以一个统一的形式来回答。因为字符串的自动机本质是相同的。

    对串B建立后缀自动机来识别子串,建立序列自动机来识别子序列,从左到右枚举A串并在B自动机上进行。(序列自动机没有fail边,但这里不需要)

    先考虑识别串A的子序列,设$f_x$表示自动机中节点x识别到的A的最短子序列。

    对于A的子序列,从左到右枚举当前字母c,对B自动机中的每个节点都进行转移,假设x+c=y,那么:

    $$f_y=min{ f_y,f_x+1}$$

    如果y=null,那么贡献答案$ans=min{ ans,f_x+1}$。

    原理是:字母c可以接在自动机识别了的所有子序列的后面形成新的子序列。

    这里要注意更新顺序,为了满足无后效性,序列自动机要从后往前更新,后缀自动机要按Parent树从下往上更新(trans边不可能返祖)。

    在考虑识别串A的子串,c只能接在所有以c前一位结尾的子串后面,那么只要每次转移到$f_y$时初始化$f_x=inf$即可。另外注意根节点不能置为inf(要接新子串)。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=2010,inf=0x3f3f3f3f;
    int n,m,last,size,root,pre[maxn],ch[maxn][26],f[maxn*2],w[maxn],b[maxn*2];
    char s[maxn],a[maxn];
    struct tree{int len,fa,t[26];}t[maxn*2];//
    void insert_SAM(int c){
        int np=++size;
        t[np].len=t[last].len+1;
        int x=last;
        last=np;
        while(x&&!t[x].t[c])t[x].t[c]=np,x=t[x].fa;
        if(!x)t[np].fa=root;else{
            int y=t[x].t[c];
            if(t[y].len==t[x].len+1)t[np].fa=y;else{
                int nq=++size;
                t[nq]=t[y];//
                t[nq].len=t[x].len+1;
                t[nq].fa=t[y].fa;t[y].fa=t[np].fa=nq;
                while(x&&t[x].t[c]==y)t[x].t[c]=nq,x=t[x].fa;//
            }
        }
    }
    void build(){
        last=size=root=1;
        for(int i=1;i<=m;i++)insert_SAM(s[i]-'a');
        for(int i=1;i<=m;i++){
            int c=s[i]-'a';
            for(int j=i-1;j>=pre[c];j--)ch[j][c]=i;
            pre[c]=i;
        }
        for(int i=1;i<=size;i++)w[t[i].len]++;
        for(int i=1;i<=m;i++)w[i]+=w[i-1];
        for(int i=1;i<=size;i++)b[w[t[i].len]--]=i;
    }
    int trans(int x,int c,int y){
        if(!y)return t[x].t[c];
        else return ch[x][c];
    }
    void solve(int A,int B){
        memset(f,0x3f,sizeof(f));
        f[B^1]=0;
        int ans=inf;
        for(int i=1;i<=n;i++){
            int c=a[i]-'a';
            for(int z=(B?m:size);z>=(B^1);z--){
                int x=B?z:b[z];
                int y=trans(x,c,B);
                if(!y)ans=min(ans,f[x]+1);else{
                    f[y]=min(f[y],f[x]+1);if(!A&&x!=(B^1))f[x]=inf;
                }
            }
        }
        printf("%d
    ",ans==inf?-1:ans);
    }        
    int main(){
        scanf("%s%s",a+1,s+1);n=strlen(a+1);m=strlen(s+1);
        build();
        solve(0,0);solve(0,1);solve(1,0);solve(1,1);
        return 0;
    }
    View Code
  • 相关阅读:
    DRUPAL-PSA-CORE-2014-005 && CVE-2014-3704 Drupal 7.31 SQL Injection Vulnerability /includes/database/database.inc Analysis
    WDCP(WDlinux Control Panel) mysql/add_user.php、mysql/add_db.php Authentication Loss
    Penetration Testing、Security Testing、Automation Testing
    Tomcat Server Configuration Automation Reinforcement
    Xcon2014 && Geekpwn2014
    phpMyadmin /scripts/setup.php Remote Code Injection && Execution CVE-2009-1151
    Linux System Log Collection、Log Integration、Log Analysis System Building Learning
    The Linux Process Principle,NameSpace, PID、TID、PGID、PPID、SID、TID、TTY
    Windows Management Instrumentation WMI Security Technology Learning
    IIS FTP Server Anonymous Writeable Reinforcement, WEBDAV Anonymous Writeable Reinforcement(undone)
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8192581.html
Copyright © 2011-2022 走看看