hdu4763---Theme Section

Theme Section

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1411    Accepted Submission(s): 712


Problem Description
It's time for music! A lot of popular musicians are invited to join us in the music festival. Each of them will play one of their representative songs. To make the programs more interesting and challenging, the hosts are going to add some constraints to the rhythm of the songs, i.e., each song is required to have a 'theme section'. The theme section shall be played at the beginning, the middle, and the end of each song. More specifically, given a theme section E, the song will be in the format of 'EAEBE', where section A and section B could have arbitrary number of notes. Note that there are 26 types of notes, denoted by lower case letters 'a' - 'z'.

To get well prepared for the festival, the hosts want to know the maximum possible length of the theme section of each song. Can you help us?
 

Input
The integer N in the first line denotes the total number of songs in the festival. Each of the following N lines consists of one string, indicating the notes of the i-th (1 <= i <= N) song. The length of the string will not exceed 10^6.
 

Output
There will be N lines in the output, where the i-th line denotes the maximum possible length of the theme section of the i-th song.
 

Sample Input
   
   
   
   
5 xy abc aaa aaaaba aaxoaaaaa
 

Sample Output
   
   
   
   
0 0 1 1 2
 

Source
2013 ACM/ICPC Asia Regional Changchun Online
 

Recommend
liuyiding   |   We have carefully selected several similar problems for you:   5169  5168  5165  5164  5161 
 

题意其实就是要找到这个字符串的某个前缀, 它在串中至少出现了三次(末尾1次,中间一次, 开头一次)

那么我们可以用EKMP,先把next数组预处理出来(串和串本身的每一个后缀的最长公共前缀), 然后用树状数组维护大于等于next[i]的值的个数

显然符合的次数肯定大于等于3, 然后只要从后往前去找那些 i + next[i] == len 的 后缀(只有匹配到结束才说明存在某个前缀出现在后缀里),找一个最大值就行

复杂度O(nlogn)


/*************************************************************************
    > File Name: hdu4763.cpp
    > Author: ALex
    > Mail: [email protected] 
    > Created Time: 2015年02月02日 星期一 13时11分11秒
 ************************************************************************/

#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const double pi = acos(-1);
const int inf = 0x3f3f3f3f;
const double eps = 1e-15;
typedef long long LL;
typedef pair <int, int> PLL;

const int N = 1000100;
char T[N];
int next[N];
int cnt_hash[N];
int tree[N];

int lowbit (int x)
{
	return x & (-x);
}

void add (int x)
{
	for (int i = x; i <= N; i += lowbit(i))
	{
		++tree[i];
	}
}

int sum (int x)
{
	int ans = 0;
	for (int i = x; i; i -= lowbit (i))
	{
		ans += tree[i];
	}
	return ans;
}

void EKMP ()
{
	int lent = strlen (T);
	next[0] = lent;
	int i, j, p, L;
	j = 0;
	while (j + 1 < lent && T[j] == T[j + 1])
	{
		++j;
	}
	next[1] = j;
	int a = 1;
	for (int i = 2; i < lent; ++i)
	{
		p = next[a] + a - 1;
		L = next[i - a];
		if (i + L < p + 1)
		{
			next[i] = L;
		}
		else
		{
			j = max (0, p - i + 1);
			while (i + j < lent && T[i + j] == T[j])
			{
				++j;
			}
			next[i] = j;
			a = i;
		}
	}
}

int main ()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		memset (next, 0, sizeof(next));
		memset (tree, 0, sizeof(tree));
		scanf("%s", T);
		EKMP ();
		int len = strlen (T);
		int maxs = 0;
		int zero = 0;
		for (int i = 0; i < len; ++i)
		{
			if (next[i] == 0)
			{
				++zero;
				continue;
			}
			add (next[i]);
		}
		for (int i = len - 1; i >= 0; --i)
		{
			if (next[i] == 0)
			{
				continue;
			}
			if (i + next[i] - 1 != len - 1)
			{
				continue;
			}
			int cnt = len - sum (next[i] - 1) - zero;
			if (cnt >= 3)
			{
				maxs = max (maxs, next[i]);
			}
		}
		printf("%d\n", maxs);
	}
	return 0;
}


你可能感兴趣的:(树状数组,扩展kmp)