zoukankan      html  css  js  c++  java
  • 计蒜客A1623 A String Game(后缀自动机next指针dag上跑sg函数)

    给出一个字符串$s$,再给出$n$个$s$的子串,每次可以任意选一个字串加上一个字母,使得新串仍然是$s$的字串,问先手必胜还是后手必胜。

    sb套路题,字串显然直接把后缀自动机建出来,由于后缀自动机就是一个DAG,所以每次加一个字母可以认为是在图上点的转移,直接算出后缀自动机上每个点的sg函数值,将字串代入求亦或和即可。

    贴下AC代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    typedef pair <int,int> pii;
    #define rep(i,x,y) for(int i=x;i<y;i++)
    #define rept(i,x,y) for(int i=x;i<=y;i++)
    #define per(i,x,y) for(int i=x;i>=y;i--)
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    #define de(x) cout<< #x<<" = "<<x<<"
    "
    #define dd(x) cout<< #x<<" = "<<x<<" "
    #define debug() cout<<"I love Miyamizu Mitsuha forever!
    "
    #define mes(a,b) memset(a,b,sizeof a)
    const int inf=0x3f3f3f3f;
    const int maxn=1e5+5;
    class SAM
    {
        public:
            int next[maxn<<1][28],link[maxn<<1];
            ll len[maxn<<1];
            vector<int> v[maxn<<1];
            int degree[maxn<<1],sg[maxn<<1];
            queue<int> q;
            bool vis[30];
            int sz,last;
            SAM()
            {
                sz=0,last=0;
            }
            void init()
            {
                rept(i,0,sz)
                {
                    link[i]=len[i]=0;
                    rep(j,0,26) next[i][j]=0;
                }
                link[0]=-1;
                sz=last=0;
                len[0]=0;
            }
            void extend(int c)
            {
                int cur=++sz;
                len[cur]=len[last]+1;
                int p=last;
                while(p!=-1&&!next[p][c])
                {
                    next[p][c]=cur;
                    p=link[p];
                }
                if(p==-1) link[cur]=0;
                else
                {
                    int q=next[p][c];
                    if(len[p]+1==len[q]) link[cur]=q;
                    else
                    {
                        int clone=++sz;
                        len[clone]=len[p]+1;
                        for(int i=0;i<26;i++) next[clone][i]=next[q][i];
                        link[clone]=link[q];
                        while(p!=-1&&next[p][c]==q)
                        {
                            next[p][c]=clone;
                            p=link[p];
                        }
                        link[q]=link[cur]=clone;
                    }
                }
                last=cur;
            }
            void getsg()
            {
                rept(i,0,sz) v[i].clear(),degree[i]=0;
                rept(i,0,sz)
                {
                    rep(j,0,26)
                    {
                        if(next[i][j])
                        {
                            v[next[i][j]].pb(i);
                            degree[i]++;
                        }
                    }
                }
                while(!q.empty()) q.pop();
                q.push(last);
                while(!q.empty())
                {
                    int x=q.front();
                    q.pop();
                    rep(i,0,v[x].size())
                    {
                        degree[v[x][i]]--;
                        if(!degree[v[x][i]]) q.push(v[x][i]);
                    }
                    rept(i,0,26) vis[i]=0;
                    rep(i,0,26) if(next[x][i]) vis[sg[next[x][i]]]=1;
                    sg[x]=0;
                    while(vis[sg[x]]) sg[x]++;
                }
            }
            int getval(string s)
            {
                int pos=0;
                rep(i,0,s.size()) pos=next[pos][s[i]-'a'];
                return sg[pos];
            }
    }sam;
    string s;
    
    int main()
    {
        ios::sync_with_stdio(false);
        cin.tie(0);cout.tie(0);
        while(cin>>s)
        {
            sam.init();
            rep(i,0,s.size())
            {
                sam.extend(s[i]-'a');
            }
            sam.getsg();
            int n,val=0;
            cin>>n;
            string t;
            rep(i,0,n)
            {
                cin>>t;
                val^=sam.getval(t);
            }
            if(val) cout<<"Alice
    ";
            else cout<<"Bob
    ";
        }
        return 0;
    }
  • 相关阅读:
    mysql--数据库的基本操作(二)
    mysql--数据库剧本指令操作
    poj_3461 KMP算法解析
    POJ_3122 经典二分题
    LIS(最长上升子序列)的 DP 与 (贪心+二分) 两种解法
    HDU_1059 多重背包问题
    HDU-1114 完全背包+恰好装满问题
    HDU _2546 01背包问题
    POJ-1611 并查集
    HDU——Monkey and Banana 动态规划
  • 原文地址:https://www.cnblogs.com/FZUzyz/p/13893194.html
Copyright © 2011-2022 走看看