zoukankan      html  css  js  c++  java
  • Manacher(最长回文串)

    http://acm.hdu.edu.cn/showproblem.php?pid=3068

    最长回文

    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
     
    Recommend
    lcy   |   We have carefully selected several similar problems for you:  1358 1686 3336 3065 3746
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    #include <iostream>
    #include <algorithm>
    #include <iostream>
    #include<cstdio>
    #include<string>
    #include<cstring>
    #include <stdio.h>
    #include <string.h>
    using namespace std;
    const int N = 500009 ;
    int c[N] ;
    int n ;
    int p[220009] ;
    char a[110009] ;
    char b[220009];
    
    
    int main()
    {
    
        while(~scanf("%s" , a))
        {
            int lena = strlen(a);
            //对字符串进行处理,通过增加无关字符,改变偶个数的回文串
            b[0] = '$';
            b[1] = '#';
            int l = 2 ;
            for(int i = 0 ; i < lena ; i++)
            {
                b[l++] = a[i];
                b[l++] = '#' ;
            }
            b[l] = '';
            int mx = -1 ;   //最右回文右边界:指的是这个位置及之前的位置的回文子串,所到达的最右边的地方
            int len = -1 ;
            int mid ;//以mid为中心的最长回文串
            for(int i = 0 ; i < l ; i++)
            {
                //一共用四种情况
                
                if(i < mx) // 如果在之前位置的最长回文串的左边
                {
                    //下面这个表达式包含了三种情况
                    // 2 * mid - 1 为i的对称点
                    //因为对称点遍历过
                    //所以可以根据该点确定i的最长回文串的长度
                    //其中有两种情况可以直接根据对称点得出i的最长回文串长度时间复杂度为o(1);
                    //还有一种需要在r的基础上继续往两边查询。
                    p[i] = min(p[2*mid - i] , mx - i) ; 
                }
                
                else//如果在边界右边则一个一个遍历
                {
                    p[i] = 1;//p数组为记录回文字符串的以每个字符为半径的最长回文字符串的长度
                }
                while(b[i - p[i]] == b[i + p[i]])//往两边查询
                    p[i]++;
                if(mx < p[i] + i)
                {
                    mid = i ;
                    mx = p[i] + i ;
                }
                len = max(len , p[i] - 1);//记录整个字符串的最长回文字符串
            }
            cout << len << endl ;
        }
    
    
        return 0 ;
    }
  • 相关阅读:
    打印二叉树和为某一值的路径
    顺时针打印数组
    算术表达式
    堆内存与栈内存详解
    【腾讯校招在线考试附加题】将一个10进制数转换为四位定长的36进制数
    反转链表
    记录github出错及解决方案
    centos7操作防火墙
    无法在web.xml或使用此应用程序部署的jar文件中解析绝对uri:[http://java.sun.com/jsp/jstl/core]解决方法
    MyBatis联表查询——别名方式
  • 原文地址:https://www.cnblogs.com/nonames/p/11282901.html
Copyright © 2011-2022 走看看