zoukankan      html  css  js  c++  java
  • 「Codechef April Lunchtime 2015」Palindromeness

    「Codechef April Lunchtime 2015」Palindromeness

    解题思路 :

    考虑对于回文子串 (s) 贡献的定义:

    [value_s = [ s[1,lfloor frac{|s|}{2} floor] ext{ is palindrome}] imes value_{s[1,lfloor frac{|s|}{2} floor]} + 1 ]

    也就是说对于每一个回文子串,只需要判断其前一半的字符是不是回文串并得到贡献即可。

    于是建出回文树,可以通过跳 (fail) 得到其所有回文前缀,用倍增找到第一个长度小于等于一半的回文前缀,判断其长度是否恰好是一半并继承贡献。

    (size_u) 表示回文树上一个节点所代表的回文串的 (right) 集合大小,则

    [Ans =sum_{u ext{ in pam}} size_u imes value_u ]

    总复杂度 (O(|s|log|s|))

    /*program by mangoyang*/
    #include<bits/stdc++.h>
    #define inf ((int)(1e9))
    #define Max(a, b) ((a) > (b) ? (a) : (b))
    #define Min(a, b) ((a) < (b) ? (a) : (b))
    typedef long long ll;
    using namespace std;
    template <class T>
    inline void read(T &x){
        int f = 0, ch = 0; x = 0;
        for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = 1;
        for(; isdigit(ch); ch = getchar()) x = x * 10 + ch - 48;
        if(f) x = -x;
    }
    const int N = 200005;
    char s[N];
    namespace PAM{
    	ll ans;
    	int ch[N][26], sz[N], fa[N], len[N], f[N][21], val[N], size, tail;
    	inline int newnode(int x){ return len[++size] = x, size; }
    	inline void init(){ 
    		memset(ch, 0, sizeof(ch));
    		memset(fa, 0, sizeof(fa));
    		memset(sz, 0, sizeof(sz));
    		len[1] = -1, fa[0] = 1, size = tail = 1, ans = 0; 
    	}
    	inline void pushback(int pos){
    		int c = s[pos] - 'a', p = tail;
    		while(s[pos-len[p]-1] != s[pos]) p = fa[p];
    		if(ch[p][c]) return (void) (sz[tail=ch[p][c]]++);
    		int np = newnode(len[p] + 2), u = fa[p];
    		while(s[pos-len[u]-1] != s[pos]) u = fa[u];
    		fa[np] = ch[u][c], sz[tail=ch[p][c]=np]++;
    	}
    	inline void solve(){
    		for(int i = 1; i <= size; i++) f[i][0] = fa[i];
    		for(int j = 1; j <= 20; j++)
    			for(int i = 1; i <= size; i++)
    				f[i][j] = f[f[i][j-1]][j-1];
    		for(int i = 2; i <= size; i++){
    			val[i] = 1; int x = i;
    			for(int j = 20; ~j; j--) 
    				if(len[f[x][j]] >= len[i] / 2) x = f[x][j]; 
    			if(len[x] == len[i] / 2) val[i] += val[x];
    		}
    		for(int i = size; i > 2; i--) sz[fa[i]] += sz[i]; 
    		for(int i = 2; i <= size; i++) ans += 1ll * val[i] * sz[i];
    		cout << ans << endl;
    	}
    }
    int main(){
    	int T; read(T);
    	while(T--){
    		scanf("%s", s + 1); int n = strlen(s + 1);
    		PAM::init();
    		for(int i = 1; i <= n; i++) PAM::pushback(i);
    		PAM::solve();
    	}
    	return 0;
    }
    
  • 相关阅读:
    【笔记】Nios II PIO的说明与双向操作注意点
    【笔记】C++ 类与对象
    【连载】 FPGA Verilog HDL 系列实例矩阵键盘接口
    【笔记】C++ 指针和引用的使用
    【笔记】C++ 多态性
    VB 串口通信 MSComm控件的使用
    【笔记】C++ 继承
    【连载】 FPGA Verilog HDL 系列实例乐曲演奏
    AJAX Conrtol Toolkit——HoverMenuExtender(停靠菜单)
    AJAX Control Toolkit DropDown
  • 原文地址:https://www.cnblogs.com/mangoyang/p/10165325.html
Copyright © 2011-2022 走看看