想到上月28号去百度笔试,遇到了一道题:已知一个N(N很大)长的字符串,求最长的回文子串。
看了一些博客,有很多种方法实现,我选其中的两种方法:
1.暴力搜索法。即不使用技巧,穷举所有可能。时间复杂度为O(n^3)(时间上最长,不推荐使用),空间复杂度为O(1)。
2.由中心向两边扩展法。时间复杂度为O(n^2),空间复杂度为O(1),稍好,并且易于理解,推荐使用。
由于没有限制语言,我分别用C++和Java实现,如下:
C++:1.暴力搜索法:
#include<string>
#include<iostream>
using namespace std;
string IsPalindrome(string str){
if(str==""){
return "";
}
int n=str.length();
int maxLength=-1;
int maxIndex=0;
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
int start=i;
int end=j;
bool flag=true;
while(start<=end){
if(str[start]!=str[end]){
flag=false;
break;
}
start++;
end--;
}
int tmpLength=j-i+1;
if(flag&&tmpLength>maxLength){
maxLength=tmpLength;
maxIndex=i;
}
}
}
return str.substr(maxIndex,maxLength);
}
int main(){
string str="djdslkAABCDEAfjdl1234321skjflkdsjfkldsababasdlkfjsdwieowowwpw";
string s=IsPalindrome(str);
cout<<s<<endl;
return 0;
}
2.由中心向两边扩展法:
#include<string>
#include<iostream>
using namespace std;
string getString(string str,int l,int r){
int n=str.length();
while(l>=0&&r<=n-1&&str[l]==str[r]){
l--;
r++;
}
return str.substr(l+1,r-l-1);
}
string IsPalindrome(string str){
int n=str.length();
if(str==""){
return "";
}
string longest=str.substr(0,1);
for(int i=0;i<n-1;i++){
string p1=getString(str,i,i);
if(p1.length()>longest.length()){
longest=p1;
}
string p2=getString(str,i,i+1);
if(p2.length()>longest.length()){
longest=p2;
}
}
return longest;
}
int main(){
string str="djdslkAABCDEAfjdl1234321skjflkdsjfkldsababasdlkfjsdwieowowwpw";
string s=IsPalindrome(str);
cout<<s<<endl;
return 0;
}
Java:1.暴力搜索法:
public class Palindrome2 {
private static String longestPalindrome(String str){
if(str==""){
return "";
}
int n=str.length();
int maxLength=-1;
int beginIndex=0;
int endIndex=0;
for(int i=0;i<n;i++){
for(int j=i;j<n;j++){
int start=i;
int end=j;
boolean flag=true;
while(start<=end){
if(str.charAt(start)!=str.charAt(end)){
flag=false;
break;
}
start++;
end--;
}
int tmpLength=j-i+1;
if(flag&&tmpLength>maxLength){
maxLength=tmpLength;
beginIndex=i;
endIndex=j+1;
}
}
}
return str.substring(beginIndex,endIndex);
}
public static void main(String[] args){
String str="djdslkAABCDEAfjdl1234321skjflkdsjfkldsababasdlkfjsdwieowowwpw";
String s=longestPalindrome(str);
System.out.println(s);
}
}
2.由中心向两边扩展法:
public class Palindrome {
private static String longestPalindrome(String str){
int n=str.length();
if(str==""){
return "";
}
String longest=str.substring(0, 1);
for(int i=0;i<n-1;i++){
String p1=expandAroundCenter(str,i,i);
if(p1.length()>longest.length()){
longest=p1;
}
String p2=expandAroundCenter(str,i,i+1);
if(p2.length()>longest.length()){
longest=p2;
}
}
return longest;
}
private static String expandAroundCenter(String str,int l,int r){
int n=str.length();
while(l>=0&&r<=n-1&&str.charAt(l)==str.charAt(r)){
l--;
r++;
}
/**
* 这里要注意,c++中的str.substr(beginIndex,length)的后一个参数是从beginIndex开始的长度,
* 而java中的str.substring(beginIndex,endIndex)的后一个参数是一个下标,应不小于beginIndex,
* 并且在获取的字符串中,不包括该下标,
*/
return str.substring(l+1, r);
}
public static void main(String[] args){
String str="djdslkAABCDEAfjdl1234321skjflkdsjfkldsababasdlkfjsdwieowowwpw";
String s=longestPalindrome(str);
System.out.println(s);
}
}
以上输出结果均为:dsjfkldsababasdlkfjsd.
参考:http://www.cnblogs.com/ZJUKasuosuo/archive/2012/07/19/2599636.html