zoukankan      html  css  js  c++  java
  • bzoj4032: [HEOI2015]最短不公共子串

    Description

     在虐各种最长公共子串、子序列的题虐的不耐烦了之后,你决定反其道而行之。

    一个串的“子串”指的是它的连续的一段,例如bcd是abcdef的子串,但bde不是。
    一个串的“子序列”指的是它的可以不连续的一段,例如bde是abcdef的子串,但bdd不是。
    下面,给两个小写字母串A,B,请你计算:
    (1) A的一个最短的子串,它不是B的子串
    (2) A的一个最短的子串,它不是B的子序列
    (3) A的一个最短的子序列,它不是B的子串
    (4) A的一个最短的子序列,它不是B的子序列

    Input

    有两行,每行一个小写字母组成的字符串,分别代表A和B。

    Output

    输出4行,每行一个整数,表示以上4个问题的答案的长度。如果没有符合要求的答案,输出-1.

    对B建出后缀自动机和序列自动机

    (1)(2)问直接枚举A子串的左端点,找在自动机上第一个不能匹配到的右端点

    (3)(4)问用f[i][j]表示考虑了A串的前i个字符,在自动机上匹配到节点j的最短子序列长度,答案为f[len(A)][null]

    时间复杂度O(len(A)*len(B)+len(B)*26)

    #include<cstdio>
    #include<cstring>
    const int inf=0x3f3f3f3f;
    char s1[2007],s2[2007];
    int nx[4111][26],l[4111],fa[4111],pv=1,ptr=1,f[4007],g[4007];
    int snx[2007][26],sp=1;
    void mins(int&a,int b){if(a>b)a=b;}
    int main(){
        scanf("%s%s",s1+1,s2+1);
        int l1=strlen(s1+1);
        int l2=strlen(s2+1);
        for(int i=1;i<=l1;++i)s1[i]-='a';
        for(int i=1;i<=l2;++i)s2[i]-='a';
        for(int i=1;i<=l2;++i){
            int x=s2[i];
            for(int j=sp++;j&&!snx[j][x];--j)snx[j][x]=sp;
            int p=pv,np=++ptr;pv=np;
            l[np]=l[p]+1;
            while(p&&!nx[p][x])nx[p][x]=np,p=fa[p];
            if(!p)fa[np]=1;
            else{
                int q=nx[p][x];
                if(l[q]==l[p]+1)fa[np]=q;
                else{
                    int nq=++ptr;
                    memcpy(nx[nq],nx[q],26);
                    l[nq]=l[p]+1;
                    fa[nq]=fa[q];
                    fa[q]=fa[np]=nq;
                    while(p&&nx[p][x]==q)nx[p][x]=nq,p=fa[p];
                }
            }
        }
        int ans=inf;
        for(int i=1;i<=l1;++i){
            for(int j=i,w=1;j<=l1;++j){
                w=nx[w][s1[j]];
                if(!w){
                    mins(ans,j-i+1);
                    break;
                }
            }
        }
        printf("%d
    ",ans==inf?-1:ans);
        ans=inf;
        for(int i=1;i<=l1;++i){
            for(int j=i,w=1;j<=l1;++j){
                w=snx[w][s1[j]];
                if(!w){
                    mins(ans,j-i+1);
                    break;
                }
            }
        }
        printf("%d
    ",ans==inf?-1:ans);
        memset(f,0x3f,sizeof(int)*(ptr+1));
        memset(g,0x3f,sizeof(int)*(ptr+1));
        f[1]=g[1]=0;
        for(int i=1;i<=l1;++i){
            int x=s1[i];
            for(int j=1;j<=ptr;++j){
                mins(g[nx[j][x]],f[j]+1);
            }
            memcpy(f,g,sizeof(int)*(ptr+1));
        }
        printf("%d
    ",f[0]==inf?-1:f[0]);
        memset(f,0x3f,sizeof(int)*(sp+1));
        memset(g,0x3f,sizeof(int)*(sp+1));
        f[1]=g[1]=0;
        for(int i=1;i<=l1;++i){
            int x=s1[i];
            for(int j=1;j<=sp;++j){
                mins(g[snx[j][x]],f[j]+1);
            }
            memcpy(f,g,sizeof(int)*(sp+1));
        }
        printf("%d
    ",f[0]==inf?-1:f[0]);
        return 0;
    }
  • 相关阅读:
    Nginx-limit_req限速配置示例
    Linux-配置虚拟IP实例
    jQuery中获取a标签的值
    js时间格式化
    a标签与js的冲突
    spring MVC页面的重定向
    EL表达式遍历集合获取下标
    商城项目之实战-购物车模块
    js中得计算问题算式结果拼接成字符串怎么解决
    js中数值类型相加变成拼接字符串的问题
  • 原文地址:https://www.cnblogs.com/ccz181078/p/6180821.html
Copyright © 2011-2022 走看看