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;
    }
    

      

  • 相关阅读:
    SuperMap房产测绘成果管理平台
    SuperMap产权登记管理平台
    Android adb shell am 的用法(1)
    由浅入深谈Perl中的排序
    Android 内存监测和分析工具
    Android 网络通信
    adb server is out of date. killing...
    引导页使用ViewPager遇到OutofMemoryError的解决方案
    adb logcat 详解
    How to send mail by java mail in Android uiautomator testing?
  • 原文地址:https://www.cnblogs.com/IMGavin/p/9459313.html
Copyright © 2011-2022 走看看