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 ;
    }
  • 相关阅读:
    七牛云上传图片
    找到当前字符串中最后一个/并获取之后的字符串
    jquery正则表达式验证:验证身份证号码
    apply()与call()的区别
    js 判断字符串是否包含某字符串,String对象中查找子字符,indexOf
    改变父元素的透明度,不影响子元素的透明度—css
    c实现生产者消费者问题。 windows下。
    python基础练习 dict切片
    html+css test1
    codewars[7]-python Friend or Foe?
  • 原文地址:https://www.cnblogs.com/nonames/p/11282901.html
Copyright © 2011-2022 走看看