天天看点

回文树 (tsinsen A1280. 最长双回文串)

A1280. 最长双回文串 时间限制: 2.0s   内存限制: 512.0MB   总提交次数: 349   AC次数: 171   平均分: 65.67 将本题分享到:             查看未格式化的试题    提交    试题讨论 试题来源   中国国家队清华集训 2011-2012 第二天 问题描述   顺序和逆序读起来完全一样的串叫做回文串。比如acbca是回文串,而abc不是(abc的顺序为“abc”,逆序为“cba”,不相同)。

  输入长度为n的串S,求S的最长双回文子串T,即可将T分为两部分X,Y,(|X|,|Y|≥1)且X和Y都是回文串。 输入格式   一行由小写英文字母组成的字符串S。 输出格式   一行一个整数,表示最长双回文子串的长度。 样例输入 baacaabbacabb 样例输出 12 样例说明   从第二个字符开始的字符串aacaabbacabb可分为aacaa与bbacabb两部分,且两者都是回文串。 数据规模及限制   对于10%的数据,2≤|S|≤10 3。

  对于30%的数据,2≤|S|≤10 4。

  对于100%的数据,2≤|S|≤10 5。

  时间限制:2秒

回文树先入个门

更详细的见博客 http://blog.csdn.net/u013368721/article/details/42100363

/*======================================================
# Author: whai
#
# Last modified: 2015-10-05 15:37
#
# Filename: tsinsen_A1280.cpp
======================================================*/
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <set>
#include <map>

using namespace std;

#define LL __int64
#define PB push_back
#define P pair<int, int>
#define X first
#define Y second

const int N = 1e5 + 5;
const int M = 26;

struct PalTree {
	int nxt[N][M]; //表示编号为i的节点表示的回文串在两边添加字符c以后变成的回文串的编号
	int fail[N]; //表示节点i失配以后跳转不等于自身的节点i表示的回文串的最长后缀回文串
	int cnt[N]; //表示节点i表示的本质不同的串的个数(建树时求出的不是完全的,最后count()函数跑一遍以后才是正确的)
	int num[N]; //表示以节点i表示的最长回文串的最右端点为回文串结尾的回文串个数
	int len[N]; //表示编号为i的节点表示的回文串的长度(一个节点表示一个回文串)
	int S[N];
	int last, n, p;

	int new_node(int x) {
		memset(nxt[p], 0, sizeof(nxt[p]));
		cnt[p] = 0;
		num[p] = 0;
		len[p] = x;
		return p++;
	}

	void init() {
		p = 0;
		new_node(0);
		new_node(-1);
		last = 0;
		n = 0;
		S[n] = -1;
		fail[0] = 1;
	}

	int get_fail(int x) {
		while(S[n - len[x] - 1] != S[n]) x = fail[x];
		return x;
	}

	int add(int x) {
		x -= 'a';
		S[++n] = x;
		int cur = get_fail(last);
		if(!nxt[cur][x]) {
			int now = new_node(len[cur] + 2);
			fail[now] = nxt[get_fail(fail[cur])][x];
			nxt[cur][x] = now;
			num[now] = num[fail[now]] + 1;
		}
		last = nxt[cur][x];
		++cnt[last];
		return len[last];
	}

	void count() {
		for(int i = p - 1; i >= 0; --i)
			cnt[fail[i]] += cnt[i];
	}
};

PalTree pt;
int len[N];
char str[N];

void gao(char str[]) {
	int ans = 0;
	int n = strlen(str);
	pt.init();

	for(int i = n - 1; i >= 0; --i) {
		len[i] = pt.add(str[i]);
	}
	pt.init();
	for(int i = 0; i < n - 1; ++i) {
		ans = max(ans, pt.add(str[i]) + len[i + 1]);
	}
	printf("%d\n", ans);
}

int main() {
	while(scanf("%s", str) != EOF) {
		gao(str);
	}
	return 0;
}