• 【计蒜客】是男人就过 8 题--Pony.AI 题 A. A String Game 后缀自动机+SG函数


    【题目】A. A String Game

    【题意】给定目标串S和n个子串Ti,Alice和Bob轮流选择一个子串操作,必须且只能在子串末尾添加一个字符使得新串也是S的子串,不能操作即输,求胜利者。|S|<=10^5,n<=100。多组数据,保证Σ|S|<=3*10^7。

    【算法】后缀自动机+博弈论SG函数

    【题解】对S建SAM,每次子串操作相当于沿SAM的实边走,所以可以对SAM进行DAG上的sg函数计算,最后多个子串的sg值的异或和就是答案,非0先手必胜。

    #include<cstdio>
    #include<cstring>
    #include<cctype>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<set>
    #include<vector>
    #include<algorithm>
    #define ll long long
    #define lowbit(x) x&-x
    using namespace std;
    int read(){
        char c;int s=0,t=1;
        while(!isdigit(c=getchar()))if(c=='-')t=-1;
        do{s=s*10+c-'0';}while(isdigit(c=getchar()));
        return s*t;
    }
    int min(int a,int b){return a<b?a:b;}
    int max(int a,int b){return a<b?b:a;}
    int ab(int x){return x>0?x:-x;}
    //int MO(int x){return x>=MOD?x-MOD:x;}
    //void insert(int u,int v){tot++;e[tot].v=v;e[tot].from=first[u];first[u]=tot;}
    /*------------------------------------------------------------*/
    const int inf=0x3f3f3f3f,maxn=100010;
    
    int n,last,root,size,sg[maxn*2];
    struct st{int len,fa,t[30];}t[maxn*2];
    void insert(int c){
        int np=++size;
        for(int i=0;i<26;i++)t[np].t[i]=0;
        t[np].len=t[last].len+1;
        int x=last;
        while(x&&!t[x].t[c])t[x].t[c]=np,x=t[x].fa;
        last=np;
        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 dfs(int x){
        bool vis[28];//
        if(~sg[x])return;
        memset(vis,0,sizeof(vis));
        for(int c=0;c<26;c++)if(t[x].t[c]){
            dfs(t[x].t[c]);
            vis[sg[t[x].t[c]]]=1;
        }
        for(int i=0;i<=26;i++)if(!vis[i]){sg[x]=i;break;}
    }
    char s[maxn];
    int main(){
        while(~scanf("%s",s)){
            int m=strlen(s);
            last=size=root=1;
            for(int c=0;c<26;c++)t[1].t[c]=0;
            for(int i=0;i<m;i++)insert(s[i]-'a');
            memset(sg,-1,sizeof(sg));
            dfs(root);
            n=read();
            int ans=0;
            for(int i=1;i<=n;i++){
                int x=root;
                scanf("%s",s);m=strlen(s);
                for(int j=0;j<m;j++)x=t[x].t[s[j]-'a'];
                ans^=sg[x];
            }
            if(ans)printf("Alice
    ");else printf("Bob
    ");
        }
        return 0;
    }
    View Code

    这破题说明我是八分之一男人,哈哈哈嗝。

    。。。

  • 相关阅读:
    R语言--自定义函数证明中心极限定理
    R基础for、while、自定义函数
    R基础绘图、时间序列生成
    装R包(package)error:(as ‘lib’ is unspecified)installation of package had non-zero exit status
    GraphPad Prism中文显示错误
    SAS学笔记_chapter_library
    excel表格打印时铺满纸张
    SAS学笔记_chapter1_基本概念
    支持向量机课(SVM)(五)--SMO算法(省去公式推导,只讲其思想)
    Web前端学习-第六课HTML篇
  • 原文地址:https://www.cnblogs.com/onioncyc/p/8666830.html
Copyright © 2020-2023  润新知