• HIHOcoder 1466 后缀自动机六·重复旋律9


    思路

    后缀数组+博弈论的好题,首先对两个串都建出SAM,然后题目的要求实际上就是在SAM的trans上转移即可
    DAG的博弈是经典问题,然后dfs求出SG函数,两个游戏的组合就是把SG函数异或起来,异或是0就是先手必败,不是0就是先手必胜
    然后要求先手必胜,所以就是求异或不为0
    接下来递推的求出第k大的串即可,类似于树上的第k大的思路

    代码

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #define int long long
    using namespace std;
    const int MAXN = 100100*2;
    struct SAM{
        int trans[MAXN][26],suflink[MAXN],maxlen[MAXN],sg[MAXN],cnt;
        long long cnt_sg[MAXN][28];
        int new_state(int _maxlen,int *_trans,int _suflink){
            ++cnt;
            maxlen[cnt]=_maxlen;
            if(_trans)
                for(int i=0;i<26;i++)
                    trans[cnt][i]=_trans[i];
            suflink[cnt]=_suflink;
            return cnt;
        }
        int add_len(int u,int c){
            int z=new_state(maxlen[u]+1,NULL,0);
            while(u&&(!trans[u][c])){
                trans[u][c]=z;
                u=suflink[u];
            }
            if(!u){
                suflink[z]=1;
                return z;
            }
            int v=trans[u][c];
            if(maxlen[v]==maxlen[u]+1){
                suflink[z]=v;
                return z;    
            }
            int y=new_state(maxlen[u]+1,trans[v],suflink[v]);
            suflink[z]=suflink[v]=y;
            while(u&&trans[u][c]==v){
                trans[u][c]=y;
                u=suflink[u];
            }
            return z;
        }
        int cal_sg(int u){
            if(sg[u]!=-1)
                return sg[u];
            bool mid[30]={0};
            for(int i=0;i<26;i++){
                if(!trans[u][i])
                    continue;
                int t=cal_sg(trans[u][i]);
                mid[t]=true;
                for(int j=0;j<27;j++)
                    cnt_sg[u][j]+=cnt_sg[trans[u][i]][j];
            }
            for(int i=0;i<30;i++)
                if(!mid[i]){
                    sg[u]=i;
                    break;
                }
            cnt_sg[u][sg[u]]++;
            for(int i=0;i<27;i++)
                cnt_sg[u][27]+=cnt_sg[u][i];
            return sg[u];
        }
        void init(char *s,int len){
            int pre=1;
            cnt=1;
            for(int i=1;i<=len;i++)
                pre=add_len(pre,s[i]-'a');
            memset(sg,-1,sizeof(sg));
            cal_sg(1);
        }
    }A,B;
    int lena,lenb,mida;
    long long k;
    char sa[MAXN],sb[MAXN],ax[MAXN],bx[MAXN];
    long long calc_mid(int Ax,int Bx){
        long long ans=0;
        for(int i=0;i<27;i++)
            ans+=A.cnt_sg[Ax][i]*(B.cnt_sg[Bx][27]-B.cnt_sg[Bx][i]);
        return ans;
    }
    int dfsA(int pos,int x){
        int mid1=B.cnt_sg[1][27]-B.cnt_sg[1][A.sg[x]];
        if(mid1>=k)
            return x;
        else
            k-=mid1;
        for(int i=0;i<26;i++){
            if(!A.trans[x][i])
                continue;
            int mid2=calc_mid(A.trans[x][i],1);
            if(mid2<k)
                k-=mid2;
            else{
                ax[pos]='a'+i;
                return dfsA(pos+1,A.trans[x][i]);
            }
        }
        return -1;
    }
    int dfsB(int pos,int x){
        k-=B.sg[x]!=A.sg[mida];
        if(k==0)
            return x;
        for(int i=0;i<26;i++){
            if(!B.trans[x][i])
                continue;
            int mid2=B.cnt_sg[B.trans[x][i]][27]-B.cnt_sg[B.trans[x][i]][A.sg[mida]];
            if(mid2<k)
                k-=mid2;
            else{
                bx[pos]='a'+i;
                return dfsB(pos+1,B.trans[x][i]);
            }
        }
        return -1;
    }
    signed main(){
        scanf("%lld",&k);
        scanf("%s",sa+1);
        lena=strlen(sa+1);
        scanf("%s",sb+1);
        lenb=strlen(sb+1);
        A.init(sa,lena);
        B.init(sb,lenb);
        if((mida=dfsA(1,1))==-1){
            printf("NO
    ");
            return 0;
        }
        dfsB(1,1);
        printf("%s
    ",ax+1);
        printf("%s
    ",bx+1);
        return 0;
    }
    
  • 相关阅读:
    [原]获取openstack-pike安装包
    [原]Failed connect to mirrors.cloud.aliyuncs.com:80; Connection refused
    [原]shell批量文件增删改前后缀
    [原]CentOS 7 chrony 笔记
    [原]Docker-issue(2) http: server gave HTTP response to HTTPS client
    [原]Docker-issue(1) image name 显示为 <none>
    [原]Django(1)----Django-setting中的STATIC_URL 和STATIC_ROOT 和STATICFILES_DIRS 的区别
    [原]Django-issue(1)---postgresql数据库连接密码错误
    [转]50个极好的bootstrap 后台框架主题下载
    [原]eclipse + pydev :Error in sitecustomize; set PYTHONVERBOSE for tracaeback: KeyError: 'sitecustomize'
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10475996.html
Copyright © 2020-2023  润新知