zoukankan      html  css  js  c++  java
  • bzoj2342 双倍回文 (回文树)

    题目链接:https://darkbzoj.tk/problem/2342

    回文树(trans)指针或回文树 + 哈希即可
    注意字串长度一定要是 (4) 的倍数

    (trans指针):

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    
    const int maxn = 500010;
    const ull base = 13331;
    
    int n, tot;
    int tail, last;
    
    ull has[maxn], rhash[maxn], po[maxn];
    int ans;
    
    struct PAM{
    	int len, fail, son[30], sz, pos, trans;
    }t[maxn];
    
    char s[maxn];
    
    int Get_Fail(int x){
    	while(s[tail - t[x].len - 1] != s[tail]) x = t[x].fail;
    	return x;
    }
    
    int Get_Trans(int x, int l){
    	while(s[tail - t[x].len - 1] != s[tail] || ((t[x].len + 2) << 1) > l) x = t[x].fail;
    	return x;
    }
    
    void Extend(int x){
    	int cur = Get_Fail(last);
    	if(!t[cur].son[x]){
    		++tot;
    		t[tot].len = t[cur].len + 2;
    		t[tot].fail = t[Get_Fail(t[cur].fail)].son[x];
    		if(t[tot].len <= 2) t[tot].trans = t[tot].fail;
    		else{
    			t[tot].trans = t[Get_Trans(t[cur].trans, t[tot].len)].son[x];
    		}
    		
    		t[cur].son[x] = tot;
    	}
    	++t[t[cur].son[x]].sz;
    	last = t[cur].son[x];
    }
    
    void count(){
    	for(int i = tot ; i >= 2 ; --i){
    		t[t[i].fail].sz += t[i].sz;
    	}
    }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	po[0] = 1;
    	for(int i = 1 ; i <= 500000 ; ++i) po[i] = po[i - 1] * base;
    		
    		n = read();
    		scanf("%s", s + 1);
    		
    		for(int i = 1 ; i <= n ; ++i) has[i] = has[i - 1] * base + s[i] - 'a';
    		rhash[n + 1] = 0;
    		for(int i = n ; i >= 1 ; --i) rhash[i] = rhash[i + 1] * base + s[i] - 'a';
    		
    		t[0].len = 0, t[1].len = -1;
    		t[0].fail = t[1].fail = 1;
    		last = 1; tot = 1;
    		
    		for(tail = 1 ; tail <= n ; ++tail){
    			Extend(s[tail] - 'a');
    		}
    		
    		count();
    		
    		for(int i = 2 ; i <= tot ; ++i){
    			if(t[i].len % 4 != 0) continue;
    
    			if((t[t[i].trans].len << 1) == t[i].len && t[t[i].trans].len % 2 == 0){
    				ans = max(ans, t[i].len);
    			} 
    		}
    		
    		printf("%d
    ", ans);
    
    	return 0;
    }
    

    哈希:

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    
    const int maxn = 500010;
    const ull base = 13331;
    
    int n, tot;
    int tail, last;
    
    ull has[maxn], rhash[maxn], po[maxn];
    int ans;
    
    struct PAM{
    	int len, fail, son[30], sz, pos;
    }t[maxn];
    
    char s[maxn];
    
    int Get_Fail(int x){
    	while(s[tail - t[x].len - 1] != s[tail]) x = t[x].fail;
    	return x;
    }
    
    void Extend(int x){
    	int cur = Get_Fail(last);
    	if(!t[cur].son[x]){
    		++tot;
    		t[tot].len = t[cur].len + 2;
    		t[tot].fail = t[Get_Fail(t[cur].fail)].son[x];
    		t[tot].pos = tail;
    		t[cur].son[x] = tot;
    	}
    	++t[t[cur].son[x]].sz;
    	last = t[cur].son[x];
    }
    
    void count(){
    	for(int i = tot ; i >= 2 ; --i){
    		t[t[i].fail].sz += t[i].sz;
    	}
    }
    
    ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
    
    int main(){
    	po[0] = 1;
    	for(int i = 1 ; i <= 500000 ; ++i) po[i] = po[i - 1] * base;
    		
    		n = read();
    		scanf("%s", s + 1);
    		
    		for(int i = 1 ; i <= n ; ++i) has[i] = has[i - 1] * base + s[i] - 'a';
    		rhash[n + 1] = 0;
    		for(int i = n ; i >= 1 ; --i) rhash[i] = rhash[i + 1] * base + s[i] - 'a';
    		
    		t[0].len = 0, t[1].len = -1;
    		t[0].fail = t[1].fail = 1;
    		last = 1; tot = 1;
    		
    		for(tail = 1 ; tail <= n ; ++tail){
    			Extend(s[tail] - 'a');
    		}
    		
    		count();
    		
    		for(int i = 2 ; i <= tot ; ++i){
    			if(t[i].len % 4 != 0) continue;
    			int len = t[i].len / 4;
    			int mid = t[i].pos - ((t[i].len & 1) ? ((t[i].len / 2) + 1) : t[i].len / 2) + 1;
    //			printf("%d %d %d
    ", t[i].pos, t[i].len, t[i].sz);
    			
    			int HR = has[t[i].pos] - has[t[i].pos - len] * po[len];
    			int HL = rhash[mid] - rhash[mid + len] * po[len];
    			if(HL == HR){
    				ans = max(ans, t[i].len);
    			} 
    		}
    		
    		printf("%d
    ", ans);
    
    	return 0;
    }
    
  • 相关阅读:
    apache安装 mod_evasive
    sshd调优
    MySQL服务器状态变量
    MySQL查询缓存
    MySQL并发调优和IO调优
    MySQL线程独享[转]
    mysql线程缓存和表缓存
    MySQL点滴
    MySQL优化常用
    apache的prefork的详解
  • 原文地址:https://www.cnblogs.com/tuchen/p/14183457.html
Copyright © 2011-2022 走看看