zoukankan      html  css  js  c++  java
  • BZOJ 4032: [HEOI2015]最短不公共子串 后缀自动机 暴力

    4032: [HEOI2015]最短不公共子串

    题目连接:

    http://www.lydsy.com/JudgeOnline/problem.php?id=4032

    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.

    Sample Input

    aabbcc

    abcabc

    Sample Output

    2

    4

    2

    4

    Hint

    对于100%的数据,A和B的长度都不超过2000

    题意

    题解:

    bfs四合一

    答案都是最长公共子XX+1

    子串我们用后缀自动机去跑,子序列我们用dp的贪心去跑就好了

    那个dp表示从i位置走到字符j的最小位置

    注意后缀自动机要开两倍空间……因为这个,wa成傻逼了

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    const int maxn = 2e3+5;
    char s1[maxn],s2[maxn];
    int len1,len2;
    int go1[maxn][26],go2[maxn][26];
    int vis[maxn][maxn*2];
    int Son[maxn*2][26],pre[maxn*2],len[maxn*2],la=1,Now=1;
    struct SAM
    {
        void add(int x)
        {
            int p=la,np=la=++Now;
            len[np]=len[p]+1;
            for(;p&&!Son[p][x];p=pre[p])
                Son[p][x]=np;
            if(!p)
                pre[np]=1;
            else
            {
                int q=Son[p][x];
                if(len[q]==len[p]+1)
                    pre[np]=q;
                else
                {
                    int nq=++Now;
                    memcpy(Son[nq],Son[q],sizeof Son[nq]);
                    len[nq]=len[p]+1;
                    pre[nq]=pre[q];
                    pre[q]=pre[np]=nq;
                    for(;p&&Son[p][x]==q;p=pre[p])
                        Son[p][x]=nq;
                }
            }
        }
    }sam;
    
    struct node
    {
        int x,y,l;
    };
    queue<node>Q;
    void init()
    {
        memset(vis,0,sizeof(vis));
        while(!Q.empty())Q.pop();
    }
    int solve1()
    {
        init();
        for(int i=0;i<len1;i++)
            Q.push(node{i,1,0});
        while(!Q.empty())
        {
            node Now = Q.front();
            Q.pop();
            if(Now.x==len1)continue;
            int nextx=Now.x+1,nexty=Son[Now.y][s1[nextx]-'a'];
            if(nexty==0)return Now.l+1;
            if(!vis[nextx][nexty])
                vis[nextx][nexty]=1,Q.push(node{nextx,nexty,Now.l+1});
        }
        return -1;
    }
    int solve2()
    {
        init();
        for(int i=0;i<len1;i++)
            Q.push(node{i,0,0});
        while(!Q.empty())
        {
            node Now = Q.front();
            Q.pop();
            if(Now.x==len1)continue;
            int nextx=Now.x+1,nexty=go2[Now.y][s1[Now.x+1]-'a'];
            if(nexty==1e5)return Now.l+1;
            if(!vis[nextx][nexty])
                vis[nextx][nexty]=1,Q.push(node{nextx,nexty,Now.l+1});
        }
        return -1;
    }
    int solve3()
    {
        init();
        Q.push(node{0,1,0});
        while(!Q.empty())
        {
            node Now = Q.front();
            Q.pop();
            for(int i=0;i<26;i++)
            {
                int nextx=go1[Now.x][i],nexty=Son[Now.y][s1[nextx]-'a'];
                if(nextx==1e5)continue;
                if(nexty==0)return Now.l+1;
                if(!vis[nextx][nexty])
                vis[nextx][nexty]=1,Q.push(node{nextx,nexty,Now.l+1});
            }
        }
        return -1;
    }
    int solve4()
    {
        init();
        Q.push(node{0,0,0});
        while(!Q.empty())
        {
            node Now = Q.front();
            Q.pop();
            for(int i=0;i<26;i++)
            {
                int nextx=go1[Now.x][i],nexty=go2[Now.y][i];
                if(nextx==1e5)continue;
                if(nexty==1e5)return Now.l+1;
                if(!vis[nextx][nexty])
                vis[nextx][nexty]=1,Q.push(node{nextx,nexty,Now.l+1});
            }
        }
        return -1;
    }
    int main()
    {
        scanf("%s%s",s1+1,s2+1);
        len1=strlen(s1+1),len2=strlen(s2+1);
        for(int i=1;i<=len2;i++)sam.add(s2[i]-'a');
        for(int i=0;i<maxn;i++)for(int j=0;j<26;j++)
            go1[i][j]=go2[i][j]=1e5;
        for(int i=0;i<=len1;i++)
            for(int j=i+1;j<=len1;j++)
                go1[i][s1[j]-'a']=min(go1[i][s1[j]-'a'],j);
        for(int i=0;i<=len2;i++)
            for(int j=i+1;j<=len2;j++)
                go2[i][s2[j]-'a']=min(go2[i][s2[j]-'a'],j);
        printf("%d
    %d
    %d
    %d
    ",solve1(),solve2(),solve3(),solve4());
    }
  • 相关阅读:
    关于uoloadify不能显示效果原因(thinkphp5仿百度糯米)
    thinkphp3.2.3中$this->assign
    PDO
    类的声明 只能有属性和方法(属性没有括号,方法有括号)
    怎删改查
    JS鼠标事件大全
    建表以及 增。删。改。查
    建表、添加数据及数据查询
    html框架
    表的求和及计算
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5204791.html
Copyright © 2011-2022 走看看