zoukankan      html  css  js  c++  java
  • HDU 3068

    题意

    给一个字符串(s),求最长回文子串

    题解

    马拉车算法的模板题。
    首先,预处理字符串(s),在每个字符的左边和右边都插上一个特殊符号,比如#,目的是保证字符串的长度为奇数。举例来说,abc ( ightarrow) #a#b#c#abcd ( ightarrow) #a#b#c#d#。同时为了保证(while)循环不超边界,需要在处理后的字符串的头尾加上不相同的特殊字符。举例来说,#a#b#c# ( ightarrow) @#a#b#c#$。(如果声明的是全局变量,则末尾不用插特殊字符,因为在声明的时候,已经被初始化:0)
    然后,令(id:=) 先前已经找到的所有回文串中边界最远的回文串 的中心,(mx:=)先前已经找到的所有回文串中边界最远的回文串 的边界。分类讨论:

    • (i <= mx)(p[i] = min(mx - i + 1, p[2 * id - i]))。因为(i)关于(id)的对称点(j)(j = 2 * id - i))的回文串的长度已经知道,所以(p[i] = p[j])可能成立。如果(i + p[i] - 1 > mx),那么超过(mx)的那部分字符串可能不是以(i)为中心的回文串的一部分。这就是为啥这儿要取(min)
    • (i > mx),就用最朴素的方法,找(i)为中心的最长回文串

    最后,在更新(p[i])的过程中记录最大(p[i] - 1)就行

    int p[MAXN * 2];
    char ma[MAXN * 2];
    
    int Mana(char* s, int n) {
        
        int m = 1;
        // inite string s
        ma[0] = '@';
        for (int i = 0; i < n; ++i) {
            ma[m++] = '#';
            ma[m++] = s[i];
        }
        ma[m] = '#';
    
        //printf("%s
    ", ma);
    
        int id = 0, mx = 0, ans = 0;
        for (int i = 0; i < m; ++i) {
            if (i < mx) p[i] = min(mx - i + 1, p[2 * id - i]);
            else p[i] = 1;
            while(ma[i - p[i]] == ma[i + p[i]]) p[i]++;
            if (i + p[i] - 1 > mx) {
                id = i;
                mx = i + p[i] - 1;
                ans = max(ans, p[i] - 1);
            }
        }
    
        return ans;
    }
    
  • 相关阅读:
    Eclipse汉化教程
    php课程---文件操作及文件上传的代码总结
    php课程---Json格式规范需要注意的小细节
    php课程---php使用PDO方法详解(转)
    php课程---随机数
    php课程---Ajax(老师详解)
    php课程---JavaScript与Jquery的区别
    php课程---JavaScript与Jquery的区别(转)
    php课程---初学PDO
    php课程---练习(联系人信息表)
  • 原文地址:https://www.cnblogs.com/zgglj-com/p/12663214.html
Copyright © 2011-2022 走看看