zoukankan      html  css  js  c++  java
  • hdu 3068 最长回文(manacher入门)

    最长回文

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


    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算法:

    定义数组p[i]表示以i为中心的(包含i这个字符)回文串半径长

    将字符串s从前扫到后for(int i=0;i<strlen(s);++i)来计算p[i],则最大的p[i]就是最长回文串长度,则问题是如何去求p[i]?

    由于s是从前扫到后的,所以需要计算p[i]时一定已经计算好了p[1]....p[i-1]

    假设现在扫描到了i+k这个位置,现在需要计算p[i+k]

    定义maxlen是i+k位置前所有回文串中能延伸到的最右端的位置,即maxlen=p[i]+i;//p[i]+i表示最大的

    分两种情况:

    1.i+k这个位置不在前面的任何回文串中,即i+k>maxlen,则初始化p[i+k]=1;//本身是回文串

    然后p[i+k]左右延伸,即while(s[i+k+p[i+k]] == s[i+k-p[i+k]])++p[i+k]

    2.i+k这个位置被前面以位置i为中心的回文串包含,即maxlen>i+k

    这样的话p[i+k]就不是从1开始


    由于回文串的性质,可知i+k这个位置关于i与i-k对称,

    所以p[i+k]分为以下3种情况得出

    //黑色是i的回文串范围,蓝色是i-k的回文串范围,




     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <stdlib.h>
     4 #include <cmath>
     5 #include <iostream>
     6 #include <algorithm>
     7 #include <queue>
     8 using namespace std;
     9 char ss[120000],xx[230000];
    10 int len[230000];
    11 int main(void)
    12 {
    13     while(scanf("%s",ss) != -1)
    14     {
    15         int l = (int)strlen(ss);
    16         for(int i = l; i >= 0; i--)
    17         {
    18             xx[i*2+2] = ss[i];
    19             xx[i*2+1] = '#';
    20         }
    21         xx[0] = '0';
    22 
    23         memset(len,0,sizeof(len));
    24         int id = 0,maxlen = 0;
    25         for(int i = 1; i < 2* l; i++)
    26         {
    27             if(len[id] + id > i)
    28                 len[i] = min(len[2*id - i],len[id] + id - i);
    29             else
    30                 len[i] = 1;
    31             while(xx[i+len[i]]  == xx[ i - len[i] ]) len[i]++;
    32             if(len[id]+id < len[i]+i)
    33                 id = i ;
    34             maxlen = max(maxlen,len[i]);
    35         }
    36         printf("%d
    ",maxlen-1);
    37     }
    38     return 0;
    39 }
  • 相关阅读:
    Arrays工具类
    String字符串
    包装类
    程序员代码面试指南 IT名企算法与数据结构题目最优解
    【面试题】了解session和cookie吗?
    如何用STAR法则来回答「宝洁八大问」
    【算法面试】常见动态规划算法示例1-最长公共子串问题
    面试HashMap之追命5连问
    JAVA面试题(8)
    多线程面试题之原子性、可见性、有序性
  • 原文地址:https://www.cnblogs.com/henserlinda/p/4727497.html
Copyright © 2011-2022 走看看