• 初探 回文树


    来源:http://victorwonder.blog.uoj.ac/blog/146

    优点:

    • 代码好写,易于调试
    • 由于是树形,功能强大(不过由于回文串的限制,这类题目比较少)

    简述

    回文树是两棵树,每个节点代表一个回文串。第一棵树的点是长度为偶数的回文串,那第二棵肯定就是奇数的啦。
    为了方便,第一棵树的根是一个长度为(0)的串,第二棵就是为(-1)的串,不要感到奇怪,就是(-1)
    可以证明,最多只有(n)个结点((n)是串的长度)。这个可以用manacher算法来证明。

    如果某结点代表的是串ccabacc,那么它的父亲代表的串就是去掉前后两个字符cabac

    每个点还有一个fail指针,表示这个串的后缀中最长的回文串,比如babab的fail指向babbab的指向b

    现来讲讲如何构树,方法的思想和KMP,AC自动机没啥两样,看看代码就立马可以懂了。

    模板题

    apio2014 回文串
    我目前刷了个rank7,相信随着这个算法的普及,我要往下跌了。

    update

    果不其然,现在已经跌到rank25。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int MAXN = (int) 3e5 + 3;
    typedef long long i64;
    
    template <class T>
    void relax(T &a, const T &b) {
    	if (b > a) a = b;
    }
    
    int n;
    char str[MAXN];
    
    struct Node {
    	Node* s[26];
    	Node* fail;
    	int len;
    	int cnt;
    };
    
    Node mem[MAXN];
    Node* curMem = mem;
    
    Node* getFail(Node* x, int i) {
    	while (i == x->len || str[i] != str[i - x->len - 1])
    		x = x->fail;
    	return x;
    }
    
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("input.txt", "r", stdin);
    #endif
    	scanf("%s", str);
    	n = strlen(str);
    
    	Node* root0 = curMem ++;
    	Node* root1 = curMem ++;
    	root0->fail = root1;
    	root1->len = -1;
    
    	Node* cur = root1;
    
    	for (int i = 0; i < n; i ++) {
    		int p = str[i] - 'a';
    		cur = getFail(cur, i);
    		if (! cur->s[p]) {
    			Node* x = curMem ++;
    			cur->s[p] = x;
    			x->len = cur->len + 2;
    			if (cur == root1) 
    				x->fail = root0;
    			else
    				x->fail = getFail(cur->fail, i)->s[p];
    		}
    		cur = cur->s[p];
    		cur->cnt ++;
    	}
    
    	i64 ans = 0;
    	for (Node* pt = curMem - 1; pt >= mem; pt --) {
    		if (pt == root0 || pt == root1) continue;
    		pt->fail->cnt += pt->cnt;
    		relax(ans, (i64) pt->len * pt->cnt);
    	}
    	cout << ans << endl;
    
    	return 0;
    }
    
  • 相关阅读:
    JAVA heap space 内存溢出
    S数据导入
    全部物料的交期都要加上两天 V_OUT_PR
    S初始化生产环境数据
    修改邮件通知模板
    java 工具类使用
    Nginx 搭建图片服务器
    java 枚举类型 Enum
    aop设计原理(转)
    Callable+ThreadPoolExecutor实现多线程并发并获得返回值(转)
  • 原文地址:https://www.cnblogs.com/wangck/p/4369865.html
Copyright © 2020-2023  润新知