码迷,mamicode.com
首页 > Windows程序 > 详细

BZOJ 3676: [Apio2014]回文串 回文串自动机

时间:2015-04-17 23:52:14      阅读:275      评论:0      收藏:0      [点我收藏+]

标签:


裸的回文串自动机

3676: [Apio2014]回文串

Time Limit: 20 Sec  Memory Limit: 128 MB
Submit: 504  Solved: 152
[Submit][Status][Discuss]

Description

考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出 
现值”为t在s中的出现次数乘以t的长度。请你求出s的所有回文子串中的最 
大出现值。 

Input

输入只有一行,为一个只包含小写字母(a -z)的非空字符串s。 

Output


输出一个整数,为逝查回文子串的最大出现值。 

Sample Input

【样例输入l】
abacaba

【样例输入2]
www

Sample Output

【样例输出l】
7

【样例输出2]
4

HINT



一个串是回文的,当且仅当它从左到右读和从右到左读完全一样。 

在第一个样例中,回文子串有7个:a,b,c,aba,aca,bacab,abacaba,其中: 

● a出现4次,其出现值为4:1:1=4 

● b出现2次,其出现值为2:1:1=2 

● c出现1次,其出现值为l:1:l=l 

● aba出现2次,其出现值为2:1:3=6 

● aca出现1次,其出现值为1=1:3=3 

●bacab出现1次,其出现值为1:1:5=5 

● abacaba出现1次,其出现值为1:1:7=7 

故最大回文子串出现值为7。 

【数据规模与评分】 

数据满足1≤字符串长度≤300000。

Source

[Submit][Status][Discuss]

HOME Back




/* ***********************************************
Author        :CKboss
Created Time  :2015年04月17日 星期五 22时29分19秒
File Name     :BZOJ3676.cpp
************************************************ */

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstdlib>
#include <vector>
#include <queue>
#include <set>
#include <map>

using namespace std;

typedef long long int LL;

const int maxn=330000;
const int C=30;

int next[maxn][C];
int fail[maxn];
int cnt[maxn]; // 本质不同的回文串出现的次数(count后)
int num[maxn]; // 表示以节点i表示的最长回文串的最右端点为回文串结尾的回文串个数
int len[maxn]; // 节点i表示的回文串的长度
int s[maxn]; // 节点i存的字符
int last; // 新加一个字母后所形成的最长回文串表示的节点
int p; // 添加节点的个数 p-2为本质不同的回文串个数
int n; // 添加字符的个数

int newnode(int x)
{
	for(int i=0;i<C;i++) next[p][i]=0;
	cnt[p]=0; num[p]=0; len[p]=x;
	return p++;
}

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

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

void add(int c)
{
	c-='a';
	s[++n]=c;
	int cur=get_fail(last);
	if(!next[cur][c])
	{
		int now=newnode(len[cur]+2);
		fail[now]=next[get_fail(fail[cur])][c];
		next[cur][c]=now;
		num[now]=num[fail[now]]+1;
	}
	last=next[cur][c];
	cnt[last]++;
}

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

char str[maxn];

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

	while(scanf("%s",str)!=EOF)
	{
		init();
		for(int i=0,sz=strlen(str);i<sz;i++) add(str[i]);
		count();
		LL ans=1;
		for(int i=2;i<p;i++) ans=max(ans,1LL*len[i]*cnt[i]);
		printf("%lld\n",ans);
	}
    
    return 0;
}



BZOJ 3676: [Apio2014]回文串 回文串自动机

标签:

原文地址:http://blog.csdn.net/ck_boss/article/details/45103817

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!