POJ - 3974 Palindrome

Description
Andy the smart computer science student was attending an algorithms class when the professor asked the students a simple question, "Can you propose an efficient algorithm to find the length of the largest palindrome in a string?"

A string is said to be a palindrome if it reads the same both forwards and backwards, for example "madam" is a palindrome while "acm" is not.

The students recognized that this is a classical problem but couldn't come up with a solution better than iterating over all substrings and checking whether they are palindrome or not, obviously this algorithm is not efficient at all, after a while Andy raised his hand and said "Okay, I've a better algorithm" and before he starts to explain his idea he stopped for a moment and then said "Well, I've an even better algorithm!".

If you think you know Andy's final solution then prove it! Given a string of at most 1000000 characters find and print the length of the largest palindrome inside this string.

Input
Your program will be tested on at most 30 test cases, each test case is given as a string of at most 1000000 lowercase characters on a line by itself. The input is terminated by a line that starts with the string "END" (quotes for clarity).

Output
For each test case in the input print the test case number and the length of the largest palindrome.

Sample Input

abcbabcbabcba
abacacbaaaab
END

Sample Output

Case 1: 13
Case 2: 6

 

题目大意:求最长回文串

对于最长回文串,有一个时间和空间都是O(n)的算法,叫manacher算法

首先我们在每个字符两边都加入一个#,然后不管奇回文串还是偶回文串就都变成了奇回文串

然后我们求一个数组p[i],表示以i为中心的回文串最多往右侧延伸多长

关键就是怎么求这个p数组

假设我们已经求出了p[1]到p[i-1],我们记录一个回文串右端最右边的右端点和中心,分别记为maxr和id

如果这个右端点超过了i(maxr>i),那么我们可以先算出p[i]的一个初始值,即i在在这个回文串中对应的位置j的p[j]

但是这个不一定是对的,因为以j为中心的回文串不一定被以id为中心的回文串所包含,所以还要与maxr-i做一个min

然后再向两边扩展

可以证明这个是O(n)的

假设maxr小于i,那么从i往右暴力扩展,同时会更新maxr

如果maxr大于i,那么以i为中心的回文串就有可能确定了,不能再向两边扩展了,那么这个操作是O(1)的

如果没有确定那么以i为中心的初始回文串就一定是延伸到了maxr,然后暴力扩展

maxr一直是递增的,最多增加到n,所以扩展的操作加起来是O(n)的

所以就是O(n)的时间了

 1 const

 2     maxn=1000010;

 3 var

 4     f:array[0..maxn*2]of longint;

 5     a:array[0..maxn*2]of byte;

 6     s:ansistring;

 7     time:longint;

 8 

 9 function min(x,y:longint):longint;

10 begin

11     if x<y then exit(x);

12     exit(y);

13 end;

14 

15 procedure work;

16 var

17     max,id,i,ans:longint;

18 begin

19     for i:=1 to length(s) do

20       a[i<<1]:=ord(s[i]);

21     max:=0;

22     id:=0;

23     for i:=1 to length(s)<<1+1 do

24       begin

25         if max>i then f[i]:=min(f[2*id-i],max-i)

26         else f[i]:=1;

27         while a[i+f[i]]=a[i-f[i]] do

28           inc(f[i]);

29         if i+f[i]>max then

30         begin

31           max:=i+f[i];

32           id:=i;

33         end;

34       end;

35     ans:=0;

36     for i:=1 to length(s)<<1+1 do

37       if f[i]-1>ans then ans:=f[i]-1;

38     writeln('Case ',time,': ',ans);

39 end;

40 

41 begin

42     readln(s);

43     a[0]:=200;

44     while s<>'END' do

45       begin

46         inc(time);

47         work;

48         readln(s);

49       end;

50 end.
View Code

 

你可能感兴趣的:(poj)