zoukankan      html  css  js  c++  java
  • 是男人就过 8 题--Pony.AI 题A String Game(博弈 SG 后缀自动机)

    将每个单轮的SG函数抑或可得最终结果。

    为了计算SG函数,先对主串用后缀自动机处理,对输入的每个子串,先在自动机上走到对应串的节点,然后枚举后续状态,这些状态即为SG函数对应的后继状态,求SG函数,并将结果保存,否则会超时。

    //http://www.cnblogs.com/IMGavin/
    //https://nanti.jisuanke.com/t/24852
    #include <iostream>
    #include <stdio.h>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #include <vector>
    #include <map>
    #include <stack>
    #include <set>
    #include <bitset>
    #include <algorithm>
    using namespace std;
    
    typedef long long LL;
    #define gets(A) fgets(A, 1e8, stdin)
    const int INF = 0x3F3F3F3F, N = 200008, MOD = 1003;
    
    const int CH = 26;
    
    struct Node{
    	int ch[CH], fa, len, sg;
    	void init(){
    		fa = -1;
    		len = 0;
    		sg = -1;
    		memset(ch, 0xff, sizeof(ch));
    	}
    }sn[N];
    
    struct SAM{
    	int cnt, last;
    	SAM(){
    		cnt = last = 0;
    		sn[cnt++].init();
    	}
    
    	int newnode(){
    		sn[cnt].init();
    		return cnt++;
    	}
    
    	void add(int x){
    		//当前串T,加入字符x,p=ST(T),end=ST(Tx)
    		int end = newnode();
    		sn[end].len = sn[last].len + 1;
    		int v = last;
    		//对p的所有没有标号x边的祖先v,trans(v,x) = end
    		for(; v != -1 && sn[v].ch[x] == -1; v = sn[v].fa){
    			sn[v].ch[x] = end;
    		}
    		//查找p的第一个有x边的祖先v,若无,则fa[end]=root
    		if(v == -1){
    			sn[end].fa = 0;
    		}else{
    			//q=trans(v,x)若Max(q)==Max(v)+1,则fa[end]=q
    			int q = sn[v].ch[x];
    			if(sn[v].len + 1 == sn[q].len){
    				sn[end].fa = q;
    			}else{
    				//否则新建节点nq,trans(nq,*)=trans(q,x)
    				//祖先关系由q->fa[q],改为q->nq->fa[q](更改前的fa[q])
    				int nq = newnode();
    				sn[nq] = sn[q];
    				sn[nq].len = sn[v].len + 1;
    				sn[end].fa = sn[q].fa = nq;
    				//对trans(v,x)==q的v,trans(v,x)改为nq
    				for(; v != -1 && sn[v].ch[x] == q; v = sn[v].fa){
    					sn[v].ch[x] = nq;
    				}
    
    			}
    		}
    
    		last = end;
    	}
    
    };
    
    char str[N], p[N];
    
    int dfs(int d){
    	if(sn[d].sg != -1){
    		return sn[d].sg;
    	}
    	bool st[27];
    	memset(st, 0, sizeof(st));
    	for(int i = 0; i < 26; i++){
    		if(sn[d].ch[i] != -1){
    			int sg = dfs(sn[d].ch[i]);
    			if(sg <= 26){
    				st[sg] = true;
    			}
    		}
    	}
    	for(int i = 0; i <= 26; i++){
    		if(!st[i]){
    			sn[d].sg = i;
    			return i;
    		}
    	}
    
    }
    
    int main(){
    	//freopen("out.txt", "w", stdout);
    	while(~scanf("%s", str)){
    		SAM sa;
    		for(int i = 0; str[i]; i++){
    			sa.add(str[i] - 'a');
    		}
    		int t, ans = 0;
    		scanf("%d", &t);
    		while(t--){
    			scanf("%s", p);
    			int st = 0;
    			for(int i = 0; p[i]; i++){
    				st = sn[st].ch[p[i] - 'a'];
    			}
    			ans ^= dfs(st);
    		}
    		if(ans){
    			printf("Alice
    ");
    		}else{
    			printf("Bob
    ");
    		}
    
    	}
    	
    
    	return 0;
    }
    

      

  • 相关阅读:
    怎么样使图片高度与宽度成比例自适应
    css文本溢出隐藏显示省略号(单行+多行)
    Monkey脚本API简介
    Monkey自动化测试
    MonkeyRunner自动化测试
    Shell逐行读取文件的3种方法
    shell脚本中调用其他脚本的三种方法
    CPU测试--通过proc获取CPU信息
    CPU测试--查看cpu占用率
    shell脚本如何获取当前时间
  • 原文地址:https://www.cnblogs.com/IMGavin/p/9459313.html
Copyright © 2011-2022 走看看