新男人八题---AStringGame

终于完成进度男人1/8,为了这题学了sam= =

题意先有一个串,n个子串,两个人轮流每次在子串上加字符,要求加完后还是原串的子串,最后不能加的就是输者,求赢的人

解法:sam之后在构造的状态图上跑sg函数,这题的sg状态不会超过26,所以直接枚举所有状态即可,然后记忆化搜索求sg函数,最后异或起来就是答案了

//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//#pragma GCC optimize("unroll-loops")
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pii pair<int,int>
#define ull unsigned long long
#define base 1000000000000000000ll
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-12;
const int N=200000+10,maxn=100000+10;//,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f;

char s[N],p[N];
struct SAM{
    int last,cnt;
    int ch[N<<1][26],fa[N<<1],l[N<<1];
    int sg[N<<1];
    void ins(int c){
        int p=last,np=++cnt;last=np;l[np]=l[p]+1;
        for(;p&&!ch[p][c];p=fa[p])ch[p][c]=np;
        if(!p)fa[np]=1;
        else{
            int q=ch[p][c];
            if(l[p]+1==l[q])fa[np]=q;
            else{
                int nq=++cnt;l[nq]=l[p]+1;
                memcpy(ch[nq],ch[q],sizeof(ch[q]));
                fa[nq]=fa[q];fa[q]=fa[np]=nq;
                for(;ch[p][c]==q;p=fa[p])ch[p][c]=nq;
            }
        }
    }
    void build(){
        memset(ch,0,sizeof ch);
        memset(fa,0,sizeof fa);
        memset(l,0,sizeof l);
        memset(sg,-1,sizeof sg);
        int len=strlen(s+1);
        last=cnt=1;
        for(int i=1;i<=len;i++)ins(s[i]-‘a‘);
        getsg(1);
//        debug();
    }
    void debug()
    {
        for(int i=1;i<=cnt;i++)
        {
            printf("%d ",i);
            for(int j=0;j<26;j++)
                printf("%d ",ch[i][j]);
            printf("---%d %d %d\n",fa[i],sg[i],l[i]);
        }
    }
    int getsg(int now)
    {
        if(sg[now]!=-1)return sg[now];
        bool vis[31];
        for(int i=0;i<=30;i++)vis[i]=0;
        for(int i=0;i<26;i++)
        {
            if(ch[now][i])
            {
                if(sg[ch[now][i]]==-1)getsg(ch[now][i]);
                vis[sg[ch[now][i]]]=1;
            }
        }
        for(int i=0;i<=30;i++)
        {
            if(!vis[i])
            {
                sg[now]=i;
                return sg[now];
            }
        }
        return sg[now];
    }
    int calsg()
    {
        int len=strlen(p+1),now=1;
        for(int i=1;i<=len;i++)
            now=ch[now][p[i]-‘a‘];
        return sg[now];
    }
}sam;
int main()
{
    while(~scanf("%s",s+1))
    {
        sam.build();
        int n;
        scanf("%d",&n);
        int x=0;
        for(int i=0;i<n;i++)
        {
            scanf("%s",p+1);
            x^=sam.calsg();
        }
        if(x)puts("Alice");
        else puts("Bob");
    }
    return 0;
}
/********************

********************/

原文地址:https://www.cnblogs.com/acjiumeng/p/8686081.html

时间: 2024-11-13 09:27:16

新男人八题---AStringGame的相关文章

LCT男人八题系列

楼教的男人八题名气甚大,今天做了一道感觉还是涨了不少姿势的,然而估计之后的每道题都要看题解吧,姑且先记录一下.以后再做再更 1737 Connected Graph 1100 [email protected] 1738 An old Stone Game 407 [email protected] 1739 Tony's Tour 671 [email protected] 1740 A New Stone Game 2240 [email protected] 1741 Tree 1728

poj 1741 楼教主男人八题之一:树分治

http://poj.org/problem?id=1741 Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an integer k,for every pair (u,v) of vertices is called valid

poj 1743 Musical Theme(男人八题&amp;后缀数组第一题)

Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 17298   Accepted: 5939 Description A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the range 1..88, each representing a key on the

POJ1742 Coins(男人八题之一)

前言 大名鼎鼎的男人八题,终于见识了... 题面 http://poj.org/problem?id=1742 分析 § 1 多重背包 这很显然是一个完全背包问题,考虑转移方程: DP[i][j]表示用前i种硬币能否取到金额j,ture表示可以,false表示不行. 则有 DP[i][j] = DP[i - 1][j] | DP[i - 1][j - k * Ai], 0 ≤ k ≤ Ci, j - k * Ai ≥ 0 这是一个O(N3)的算法,考虑到数据范围1 ≤ N ≤ 100, M ≤

男人八题2019

打的第三年男人八题了= = 感觉自己可能能创造一个EZ历史上打过最多男人八题的人(嘤嘤嘤我明明是妹子啊 考场上是5题 目前补了7题 目录 Biology Chemistry Chinese English Geography History Math Physics Biology 模拟= = //Love and Freedom. #include<cstdio> #include<algorithm> #include<cstring> #include<cm

POJ 1741 男人八题——树分治

Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 23829   Accepted: 7900 Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an

poj1737~poj1744——ltc男人八题

准备开刷这充满神秘感的八道题,虽然我不是男的... 完成度:3/8 2016.7.~?   poj1742 Coins 题意:给你n种面值的硬币和每种硬币的数量.求1~m中有多少个可以用这些硬币组成. 算法:dp 解析:dp[i][j]表示用前i中硬币组成j时第i种硬币剩余的枚数(若不能组成j则为-1) 考虑以下四种情况: (1)若dp[i-1][j]>=0,则无需第i种硬币,为c[i] (2)若val[i]>j,面值太大,则为-1 (3)若dp[i][j-val[i]]<=0,无法组成

hdu 2844 Coins 多重背包模板题 ,二进制优化。据说是楼教主的男人八题之一

Coins Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 8052    Accepted Submission(s): 3291 Problem Description Whuacmers use coins.They have coins of value A1,A2,A3...An Silverland dollar. One

男人八题_POJ-1741

题目链接:http://poj.org/problem?id=1741 树分治相关论文:http://wenku.baidu.com/view/60c6aa1ffc4ffe473368aba8.html 由于论文中有该题的讲解,所以便不再赘述.代码如下 1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std;