HDU3068最长回文 Manacher算法

49 篇文章 0 订阅
7 篇文章 0 订阅



最长回文

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


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
 



参考:manacher算法


算法的基本思路是这样的:把原串每个字符中间用一个串中没出现过的字符分隔#开来(统一奇偶),

同时为了防止越界,在字符串的首部也加入一个特殊符,但是与分隔符不同。

同时字符串的末尾也加入′\0′。


算法的核心:用辅助数组p记录以每个字符为核心的最长回文字符串半径。

也就是p[i]记录了以str[i]为中心的最长回文字符串半径。p[i]最小为1,

此时回文字符串就是字符串本身。示例:原字符串′abba′,处理后的新串′#a#b#b#a#\0’,

得到对应的辅助数组p=[0,1,1,2,1,2,5,2,2,1]。


#include
   
   
    
    
#include
    
    
     
     
#include
     
     
      
      
using namespace std;
#define N 1000010
char str[N];
char tmp[N<<1];
int len[N<<1];
int main()
{
    int t=1,i,l;
    while(scanf("%s",str)==1)
    {
        l=strlen(str);
        l*=2;
        tmp[0]='@';
        for(i=1; i<=l; i+=2)
        {
            tmp[i]=0;
            tmp[i+1]=str[i>>1];
        }
        tmp[l+1]=0;
        tmp[l+2]='$';   ///防止越界
        tmp[l+3]=0;
        l++;
        int id=0;   ///id当前len[i]的最大位置i
        int mx=0;   ///mx即为当前计算回文串最右边字符的最大值
        int ans=0;  ///回文串最大值
        for(i=1; i<=l; i++)
        {
            len[i]=mx
      
      
       
       =mx,要从头开始匹配
            while(tmp[i+len[i]]==tmp[i-len[i]])
                len[i]++;
            if(len[i]+i>mx)///若新计算的回文串右端点位置大于mx,要更新id和mx的值
            {
                mx=len[i]+i;
                id=i;
            }
            ans=ans>len[i]?ans:len[i];///1~i回文串最大值
        }
        printf("%d\n",ans-1);
    }
    return 0;
}
      
      
     
     
    
    
   
   



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值