hdu 3068 最长回文 扩展KMP

hdu 3068 最长回文 扩展KMP


题目链接......

最长回文

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1301    Accepted Submission(s): 313


Problem Description
给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度.
回文就是正反读都是一样的字符串,如aba, abba等
 

Input
输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S
两组case之间由空行隔开(该空行不用处理)
字符串长度len <= 110000
 

Output
每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度.
 

Sample Input

    
    
    
    
aaaa abab
 

Sample Output

    
    
    
    
4 3
 

Source
2009 Multi-University Training Contest 16 - Host by NIT
 

Recommend
lcy

代码:

#include  < iostream >
#include 
< cstdio >
#include 
< string >
#include 
< cstring >
using   namespace  std;

#define  max_size 110010

int  next1[max_size];
int  next2[max_size];
int  next[max_size];
int  ans;

char  a[max_size];
char  b[max_size];

void  getNext1( int  n)
{
     
int  i, j, k;
     next[
0 =  n;
     j 
=   0 ;
     
while  (j  +   1   <  n  &&  b[j]  ==  b[j + 1 ])j ++ ;
     next[
1 =  j;
     k 
=   1 ;
     
for  (i  =   2 ; i  <  n; i ++ )
     {
         
if  (next[i - k]  +  i  <  next[k]  +  k)
            next[i] 
=  next[i - k];
         
else
         {
             j 
=  next[k]  +  k  -  i;
             
if  (j  <   0 )j  =   0 ;
             
while  (i + <  n  &&  b[j]  ==  b[i + j])j ++ ;
             next[i] 
=  j;
             k 
=  i;
         }
     }
}

void  getNext2( char   * s,  int   * nexts,  int  n,  int  m)
{
     getNext1(m);
     
int  i, j, k;
     j 
=   0 ;
     k 
=   0 ;
     
while  (s[j]  ==  b[j])j ++ ;
     nexts[
0 =  j;
     
     
for  (i  =   1 ; i  <  n; i ++ )
     {
         
if  (next[i - k]  +  i  <  nexts[k]  +  k)
             nexts[i] 
=  next[i - k];
         
else
         {
             j 
=  nexts[k]  +  k  -  i;
             
if  (j  <   0 ) j  =   0 ;
             
while  (i  +  j  <  n  &&  s[i + j]  ==  b[j])j ++ ;
             nexts[i] 
=  j;
             k 
=  i;
         }
     }
}

void  res( char   * s,  int  n)
{
     
char  st;
     
int  len  =  (n >> 1 );
     
for  ( int  i  =   0 ; i  <  len; i ++ )
     {
         st 
=  s[i];
         s[i] 
=  s[n - i - 1 ];
         s[n
- i - 1 =  st;
     }
}

void  find( char   * s,  int  n)
{
     
if  (ans  >=  n  ||  n  <   2 ) return ;
     
int  i, k, x;
     
int  mid;
     
     mid 
=  (n >> 1 );
     
     
for  (i  =  mid; i  <  n; i ++ )b[i - mid]  =  s[i];
     b[i
- mid]  =   0 ;
     res(s, n);
     getNext2(s, next1, n, i
- mid);
     
     res(s, n);
     
for  (i  =   0 ; i  <  mid; i ++ )
       b[i] 
=  s[mid - i - 1 ];
     b[i] 
=   0 ;
     getNext2(s, next2, n, mid);
     
     next1[n] 
=  next2[n]  =   0 ;
     
     
for  (i  =   0 ; i  <  mid; i ++ )
     {
         
if  (next2[i]  >=  mid  -  i)
         {
             x 
=  mid  -  i  +   2   *  next1[n - i];
             
if  (ans  <  x)ans  =  x;
         }
     }
     
for  (i  =  mid; i  <  n; i ++ )
     {
         
if  (next1[n - i]  >=  i  -  mid)
         {
             x 
=  i  -  mid  +   2 * next2[i];
             
if  (ans  <  x) ans  =  x;
         }
     }
     find(s, mid);
     find(s
+ mid, n - mid);
}

int  main()
{
    
int   n;
    
while  (scanf( " %s " , a)  !=  EOF)
    {
          n 
=  strlen(a);
          ans 
=   1 ;
          find(a, n);
          printf(
" %d\n " , ans);
    }
    
return   0 ;
}

你可能感兴趣的:(hdu 3068 最长回文 扩展KMP)