[百度]2014百度校园招聘之最长回文串

【题目】

给你一个字符串,找出该字符串中对称的子字符串的最大长度。即求最大回文串。

【思路1】暴力法

即不使用技巧,穷举所有可能。时间复杂度为O(n^3)(时间上最长,不推荐使用),空间复杂度为O(1)。

本思路是从最大长度的字串开始,而不是从最小开始。假如说给定的字符串为len,先遍历长度为len的字串是否为回文串,如果是停止,

如果不是遍历长度为len-1的字串是否是回文串,一次类推。

#include <iostream>
using namespace std;
//是否是回文串
bool IsPalindromeSubNumber(string num){
    int len = num.length();
    for(int i = 0,j=len-1;i < j;i++,j--){
        if(num[i] != num[j]){
            return false;
        }
    }
    return true;
}
void MaxSubPalindromeNumber(string num){
    bool result;
    bool flag = false;
    int len = num.length();
	//遍历字串的长度
    for(int i = len;i > 0;i--){
		//遍历字串的起始位置
        for(int j = 0;j+i <= len;j++){
            result = IsPalindromeSubNumber(num.substr(j,i));
            if(result){
                flag = true;
                cout<<num.substr(j,i)<<endl;
            }
        }
        if(flag){
            break;
        }
    }
}

int main(){
    string num = "djdslkAABCDEAfjdl1234321skjflkdsjfkldsababasdlkfjsdwieowowwpw";
    MaxSubPalindromeNumber(num);
    return 0;
}

【思路2】

假设现在已经遍历到第 i 个字符,要找出以该字符为“中心”的最长对称字符串,我们需要用另两个指针分别向前和向后移动,直到指针到达字符串两端或者两个指针所指的字符不相等。因为对称子字符串有两种情况,所以需要写出两种情况下的代码:

(1) 第 i 个字符是该对称字符串的真正的中心,也就是说该对称字符串以第 i 个字符对称, 比如: “aba”

(2)第 i 个字符串是对称字符串的其中一个中心。比如“abba”。

所以遍历到每个字符都要考虑两种情况,它可能是在奇数个回文串中或者是在偶数个回文串中

#include<string>
#include<iostream>
using namespace std;

string MaxPalindromeNumber(string str){
    int maxLen = 1,start = 0;
    int len = str.length();
    string s = str;
    int left,right;
    for(int i = 0;i < len;i++){
        //奇数字串
        int oddLen = 1;
        left = i-1;
        right = i+1;
        while(left >= 0 && right < len && str[left] == str[right]){
            left--;
            right++;
            oddLen += 2;
        }
        //更新最大长度
        if(oddLen > maxLen){
            maxLen = oddLen;
            //记录当前最大回文串的起始位置
            start = left+1;
        }
        //偶数字串
        left = i;
        right = i+1;
        int evenLen = 0;
        while(left >= 0 && right < len && str[left] == str[right]){
            left--;
            right++;
            evenLen += 2;
        }
        //更新最大长度
        if(evenLen > maxLen){
            maxLen = evenLen;
            //记录当前最大回文串的起始位置
            start = left+1;
        }
    }
    return str.substr(start,maxLen);
}

int main(){
	string str="djdslkAABCDEAfjdl1234321skjflkdsjfkldsababasdlkfjsdwieowowwpw";
	string s=MaxPalindromeNumber(str);
	cout<<s<<endl;
	return 0;
}

【思路三】Manacher算法

算法的基本思路是这样的:把原串每个字符中间用一个串中没出现过的字符分隔#开来(统一奇偶),同时为了防止越界,在字符串的首部也加入一个特殊符$,但是与分隔符不同。同时字符串的末尾也加入'\0'。算法的核心:用辅助数组p记录以每个字符为核心的最长回文字符串半径。也就是p[i]记录了以str[i]为中心的最长回文字符串半径。p[i]最小为1,此时回文字符串就是字符串本身。 
示例:原字符串 'abba’,处理后的新串 ' $#a#b#b#a#\0’,得到对应的辅助数组p=[0,1,1,2,1,2,5,2,2,1]。 

详细请看:[算法]Manacher算法之最大回文子串

#include <string.h>
#include <iostream>
#include <algorithm>
using namespace std;
//数据预处理
char* Init(char* s){
    int len = strlen(s);
    char* str = new char(2*len+4);
    str[0] = '$';
    int index = 1;
    for(int i = 0;i < len;i++){
        str[index++] = '#';
        str[index++] = s[i];
    }
    str[index++] = '#';
    str[index] = '\0';
    return str;
}

char* MaxPalindromeNumber(char* s){
    char *str = Init(s);
    int maxId = 0,center = 1;
    int len = strlen(str);
    int *p = new int[len+1];

    // MaxId为i字符之前最大回文串向右延伸的最大位置
    // id为MaxId对应的最大回文串的中心位置
    for(int i = 1;i < len;i++){
        //初步定i位置字符为中心的半径
        if(maxId > i){
            p[i] = min(maxId - i,p[2*center - i]);
        }
        else{
            p[i] = 1;
        }
        //继续确定i位置字符为中心的半径 这地方用到'$'
        while(str[i-p[i]] == str[i+p[i]]){
            p[i]++;
        }
        //更新MaxId,id
        if(p[i]+i > maxId){
            maxId = p[i] + i;
            center = i;
        }
    }
    // 最大长度
    int maxLen = 0;
    center = 1;
    for(int i = 1;i < len;i++){
        if(str[i] != '#' && p[i] - 1 > maxLen){
            maxLen = p[i] - 1;
            center = i;
        }
    }
    //提取最大回文串
    char* maxStr = new char[maxLen+1];
    int index = 0;
    for(int i = center - maxLen;i <= center + maxLen;i++){
        if(str[i] != '#'){
            maxStr[index++] = str[i];
        }
    }
    maxStr[index] = '\0';
    return maxStr;
}

int main(){
	char* str="skjflkdsjfkldsababasdlkfjsdwieowowwpw";
	cout<<MaxPalindromeNumber(str);
	return 0;
}

相关链接:

[小米]2015小米校招之回文数判断

[网易]字符串回文分割

时间: 2024-10-29 12:34:15

[百度]2014百度校园招聘之最长回文串的相关文章

Manacher&#039;s Algorithm 求解字符串的最长回文串

Manacher算法:O(n)求字符串的最长回文串 1:算法可以在O(n)的时间内求出以每一个字符为中心的最长回文串 2:算法把奇数回文串和偶数回文串统一起来考虑 3:算法大致过程是这样.先在每两个相邻字符中间插入一个分隔符,当然这个分隔符要在原串中没有出现过.一般可以用'#'分隔.这样就非常巧妙的将奇数长度回文串与偶数长度回文串统一起来考虑了(见下面的一个例子,回文串长度全为奇数了),然后用一个辅助数组rad记录以每个字符为中心的最长回文串的信息.rad[i]记录的是以字符str[i]为中心的

lintcode最长回文子串(Manacher算法)

题目来自lintcode, 链接:http://www.lintcode.com/zh-cn/problem/longest-palindromic-substring/ v最长回文子串  给出一个字符串(假设长度最长为1000),求出它的最长回文子串,你可以假定只有一个满足条件的最长回文串. v样例 给出字符串 "abcdzdcab",它的最长回文子串为 "cdzdc". v挑战 O(n2) 时间复杂度的算法是可以接受的,如果你能用 O(n) 的算法那自然更好.

hdu 3068 最长回文

点击打开链接hdu 3068 思路:manacher求解字符串最长回文串 分析:详见点击打开链接 代码: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAXN 240010 int ans; char tmpStr[MAXN]; char String[MAXN]; int rad[MAXN]; /

九度题目1528:最长回文子串

题目1528:最长回文子串 时间限制:1 秒 内存限制:128 兆 特殊判题:否 提交:781 解决:239 题目描述: 回文串就是一个正读和反读都一样的字符串,比如"level"或者"noon"等等就是回文串. 回文子串,顾名思义,即字符串中满足回文性质的子串. 给出一个只由小写英文字符a,b,c...x,y,z组成的字符串,请输出其中最长的回文子串的长度. 输入: 输入包含多个测试用例,每组测试用例输入一行由小写英文字符a,b,c...x,y,z组成的字符串,字

Longest Palindromic Substring:最长回文子串

题目链接 Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring. 求字符串的最长回文子串 算法1:暴力解法,枚举所有子串,对每个子串判断是否为回文,复杂度为O(n^3) 算法2:删除暴力解法中有很多重复的判

java-通过删改构成最长回文数问题

问题描述 通过删改构成最长回文数问题 给定一串数字,通过删除某些数字构成一个回文数,算法如何实现,最好使用java试实现.例 1234564321,删除5或者6,就构成了最长回文数. 解决方案 个人认为:首先要构成回文,是不是应该是一对称数组才行?如果是一个对称数组?就像例子一样.1234564321,length=10如果是123454321,length=9这个已经是回文了,所以长度是双数,我们可以将1234 56 4321中间的两个数(56)任意删去其一,就构成回文了.希望能够帮助你. 解

java算法-java求教,算法竞赛入门经典 3.4 最长回文子串

问题描述 java求教,算法竞赛入门经典 3.4 最长回文子串 java新手求教,关键是怎么保存s[i]在buf中的位置,谢谢 解决方案 string longestPalindromeDP(string s) { int n = s.length(); int longestBegin = 0; int maxLen = 1; bool table[1000][1000] = {false}; for (int i = 0; i < n; i++) { table[i][i] = true;

java算法-Longest Palindromic Substring 最长回文子串问题?JAVA

问题描述 Longest Palindromic Substring 最长回文子串问题?JAVA public class Solution { public String longestPalindrome(String s) { String ret = ""; for (int i = 0; i < s.length(); i++) { for (int j = 0; i - j >= 0 && i + j < s.length(); j++)

hihocoder 算法-我的hihocoder这个最长回文子串为什么报wrong answer?

问题描述 我的hihocoder这个最长回文子串为什么报wrong answer? import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner scanner = new Scanner(System.in); int n = scanner.nextInt(); for(int i = 0;i String str = scanner.next(); System.