Gym101194F-Mr. Panda and Fantastic Beasts

题意:给你n个字符串,找出一个最短的字符串,使得这个字符串只是第一个字符串的子串

解题思路:后缀数组+二分


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>

using namespace std;

#define LL long long
const int INF = 0x3f3f3f3f;
const int N=350010;

int k;

struct Sa
{
    char ch[N];
    int s[N],q,len;
    int rk[2][N],sa[N],h[N],w[N],now,m,n,vis[50009],pos;
    int rmq[N][20],lg[N],bel[N];
    vector<int>g;

    bool GetS()
    {
        n=len=0,q='z';
        scanf("%d",&k);
        for(int i=1;i<=k;i++)
        {
            scanf("%s",&ch);
            for(int j=0;ch[j];j++)
            {
                s[++n]=ch[j],bel[n]=i;
                if(i==1) len++;
            }
            s[++n]=++q;
        }
        return true;
    }

    void getsa(int z,int &m)
    {
        int x=now,y=now^=1;
        for(int i=1; i<=z; i++) rk[y][i]=n-i+1;
        for(int i=1,j=z; i<=n; i++)
            if(sa[i]>z) rk[y][++j]=sa[i]-z;
        for(int i=1; i<=m; i++) w[i]=0;
        for(int i=1; i<=n; i++) w[rk[x][rk[y][i]]]++;
        for(int i=1; i<=m; i++) w[i]+=w[i-1];
        for(int i=n; i>=1; i--) sa[w[rk[x][rk[y][i]]]--]=rk[y][i];
        for(int i=m=1; i<=n; i++)
        {
            int *a=rk[x]+sa[i],*b=rk[x]+sa[i-1];
            rk[y][sa[i]]=*a==*b&&*(a+z)==*(b+z)?m-1:m++;
        }
    }

    void getsa(int m)
    {
        now=rk[1][0]=sa[0]=s[0]=0;
        for(int i=1; i<=m; i++) w[i]=0;
        for(int i=1; i<=n; i++) w[s[i]]++;
        for(int i=1; i<=m; i++) rk[1][i]=rk[1][i-1]+(bool)w[i];
        for(int i=1; i<=m; i++) w[i]+=w[i-1];
        for(int i=1; i<=n; i++) rk[0][i]=rk[1][s[i]];
        for(int i=1; i<=n; i++) sa[w[s[i]]--]=i;
        rk[1][n+1]=rk[0][n+1]=0;
        for(int x=1,y=rk[1][m]; x<=n&&y<=n; x<<=1) getsa(x,y);
        for(int i=1,j=0; i<=n; h[rk[now][i++]]=j?j--:j)
        {
            if(rk[now][i]==1) continue;
            int k=n-max(sa[rk[now][i]-1],i);
            while(j<=k&&s[sa[rk[now][i]-1]+j]==s[i+j]) ++j;
        }
    }

    void getrmq()
    {
        h[n+1]=h[1]=lg[1]=0;
        for(int i=2; i<=n; i++)
            rmq[i][0]=h[i],lg[i]=lg[i>>1]+1;
        for(int i=1; (1<<i)<=n; i++)
        {
            for(int j=2; j<=n; j++)
            {
                if(j+(1<<i)>n+1) break;
                rmq[j][i]=min(rmq[j][i-1],rmq[j+(1<<i-1)][i-1]);
            }
        }
    }

    int lcp(int x,int y)
    {
        int l=min(rk[now][x],rk[now][y])+1,r=max(rk[now][x],rk[now][y]);
        return min(rmq[l][lg[r-l+1]],rmq[r-(1<<lg[r-l+1])+1][lg[r-l+1]]);
    }

    bool check(int x)
    {
        int cnt=0;
        for(int i=1;i<=n;i++)
        {
            if(h[i]>=x)
            {
                if(!vis[bel[sa[i]]]) vis[bel[sa[i]]]=1,cnt++,g.push_back(bel[sa[i]]);
                if(!vis[bel[sa[i-1]]]) vis[bel[sa[i-1]]]=1,cnt++,g.push_back(bel[sa[i-1]]);
            }
            else
            {
                if(cnt<=1&&bel[sa[i-1]]==1&&len-sa[i-1]+1>=x) {pos=sa[i-1];return 1;}
                cnt=0;
                int Size=g.size();
                for(int i=0;i<Size;i++) vis[g[i]]=0;
                g.clear();
            }
        }
        if(cnt<=1&&bel[sa[n]]==1&&len-sa[n]+1>=x) return 1;
        int Size=g.size();
        for(int i=0;i<Size;i++) vis[g[i]]=0;
        g.clear();
        return 0;
    }

    void work()
    {
        getsa(55000);
        int l=1,r=len,ans=0;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            if(check(mid)) {ans=mid;r=mid-1;}
            else l=mid+1;
        }
        if(!ans) {printf("Impossible\n");return ;}
        for(int i=pos;i<pos+ans;i++) printf("%c",s[i]);
        printf("\n");
    }
}sa;

int main()
{
    int t,cas=0;
    scanf("%d",&t);
    while(t--)
    {
        sa.GetS();
        printf("Case #%d: ",++cas);
        sa.work();
    }
    return 0;
}

wandb: Tracking run with wandb version 0.15.5 wandb: W&B syncing is set to `offline` in this directory. wandb: Run `wandb online` or set WANDB_MODE=online to enable cloud syncing. /home/zhangmengjie/anaconda3/envs/torch1/lib/python3.7/site-packages/gym/envs/registration.py:556: UserWarning: WARN: The environment Ant-v2 is out of date. You should consider upgrading to version `v4`. f"The environment {id} is out of date. You should consider " Error compiling Cython file: ------------------------------------------------------------ ... See c_warning_callback, which is the C wrapper to the user defined function ''' global py_warning_callback global mju_user_warning py_warning_callback = warn mju_user_warning = c_warning_callback ^ ------------------------------------------------------------ /home/zhangmengjie/anaconda3/envs/torch1/lib/python3.7/site-packages/mujoco_py/cymj.pyx:92:23: Cannot assign type 'void (const char *) except * nogil' to 'void (*)(const char *) noexcept nogil' Error compiling Cython file: ------------------------------------------------------------ ... See c_warning_callback, which is the C wrapper to the user defined function ''' global py_error_callback global mju_user_error py_error_callback = err_callback mju_user_error = c_error_callback ^ ------------------------------------------------------------ /home/zhangmengjie/anaconda3/envs/torch1/lib/python3.7/site-packages/mujoco_py/cymj.pyx:127:21: Cannot assign type 'void (const char *) except * nogil' to 'void (*)(const char *) noexcept nogil' Compiling /home/zhangmengjie/anaconda3/envs/torch1/lib/python3.7/site-packages/mujoco_py/cymj.pyx because it changed. [1/1] Cythonizing /home/zhangmengjie/anaconda3/envs/torch1/lib/python3.7/site-packages/mujoco_py/cymj.pyx wandb: Waiting for W&B process to finish... (failed 1). wandb: You can sync this run to the cloud by running: wandb: wandb sync /home/zhangmengjie/PID/Python/ERL-Re2-main/wandb/offline-run-20230721_165346-awq1hazo wandb: Find logs at: ./wandb/offline-run-20230721_165346-awq1hazo/logs
最新发布
07-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值