• HDU3068 最长回文 MANACHER+回文串


    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
     
    该题可以用扩展KMP O(N*logN)进行求解,但在学长那里知道了针对回文子串黑科技一般的O(N)算法,那就是Manacher。
    这个算法运用了很多数学上的思维及回文串本身的对称性质。
    1.在每两个字符之间填入“#”使串变为偶数长度。
    2.对数组每个元素计算以它为中心对称的半径值(p[i])
    3.求出最大的p[i]值
    4.优化,对每个元素求出p[i]值时,p[i]+i 是之前遍历过的最远的端点时,记录,此后当i小于之前记录的p[i]+i时,直接求最长的半径值。
     
    另外要注意的细节问题是,在处理过的数组首尾要加上同内容完全不同的字符如“%” "$"等作为区分,终止,防止越界。
     
     1 #include <stdio.h>
     2 #include <iostream>
     3 #include <algorithm>
     4 #include <string.h>
     5 using namespace std;
     6 
     7 
     8 char a[110010], b[220010];
     9 int p[220010];
    10 int main()
    11 {
    12     int n, ma, r, t, x;
    13     while(~scanf("%s", &a[1]))
    14     {
    15         getchar();
    16         x=strlen(a+1);
    17         b[0]='%';
    18         b[1]='#';
    19         //printf("~%d",x);
    20         for(int i=1; i<=x; i++)
    21         {
    22             b[2*i]=a[i];
    23             b[2*i+1]='#';
    24             //printf("%c%c",b[2*i],b[2*i+1]);
    25         }
    26         b[2*x+2]='$';
    27 
    28         t=ma=r=0;
    29         for(int i=1; i<=2*x+1; i++)
    30         {
    31             if(r>i)             //如果遍历的该点已经小于最长的半径,则不用考虑该点
    32             {
    33                 p[i]=min(r-i, p[t-(i-t)]);//优化避免重复匹配
    34             }
    35             else
    36             {
    37                 p[i]=1;
    38             }
    39             while(b[i+p[i]]==b[i-p[i]]) 
    40             {
    41                 p[i]++;
    42             }
    43 
    44 
    45             if(p[i]+i>r) 
    46             {
    47                 r=p[i]+i;    //记录延伸最长的posiition值
    48                 t=i; 
    49 } 50 ///// 51 if(ma<p[i]) 52 ma=p[i]; 53 } 54 printf("%d ", ma-1); 55 } 56 }
  • 相关阅读:
    javascript语法之函数案例练习
    javascript语法之函数的定义
    javascript语法之with语句
    javascript语法之for-in语句
    javascript语法之循环语句小练习
    centos 7 配置samba mount
    Centos 7 systemd.service — Service unit configuration
    Linux 下使用 ffmpeg 大批量合并 ts 文件, mp4切割文件为m3u8
    Debian 系统修改网卡ens33名称为 eth0
    star_namelist
  • 原文地址:https://www.cnblogs.com/Yumesenya/p/5347462.html
Copyright © 2020-2023  润新知