程序员笔试题---【最大回文子串】

最大的回文字串,相信大家都很熟悉了,类似的题目有过很多。

单纯的有求解字符串中的最大回文字串,例如:“abcgoogleaba”,最大的回文字串为goog,虽说aba也是回文但长度较短。

还有网易游戏考到的一道题:“abcgoogleaba”,如果是回文的话,当做一个整体输出,否则单个的输出,这个输出的格式为:a,b,c,goog,l,e,aba.

针对求最大的回文字串问题。有很多种方式,比如蛮力法。但是相信大家在笔试或者面试的时候,考官都会要求尽量的好的时间和空间复杂度。

因此我们需要寻找更好的办法。

第一、最大的回文字串

1、一般的做法,分为回文串是偶数个还是奇数个

就如上面的例子一样:abcgoogleaba,两个回文,一个是goog,另一个是:aba

#include "stdafx.h"
#include <iostream>
using namespace std;

int getMaxHuiWen(char * p,int len)
{
	int i=0,j=0;
	int max=0;
	int x,y;
	for(i=0;i<len;i++)
	{
		for(j=0;i-j>=0&&i+j<len;j++)//回文的字符个数为奇数
		{
			if(p[i-j]!=p[i+j])
				break;
			else
			{
				if(2*j+1>max)
				{
					max=2*j+1;
					x=i-j;
					y=i+j;
				}

			}
		}

		for(j=0;i-j>=0&&i+j+1<len;j++)//回文字符个数为偶数
		{
			if(p[i-j]!=p[i+j+1])
				break;
			else
			{
				if(2*j+2>max)
				{
					max=2*j+2;
					x=i-j;
					y=i+j+1;
				}

			}
		}
	}

	for(int k=x;k<=y;k++)//打印出回文
	{
		cout<<p[k];
	}
	return max;//返回最长回文的长度
}
int main(int argc, char* argv[])
{
	char *p="abcgooglrcabac";
	int len=strlen(p);
	int max=getMaxHuiWen(p,len);
	cout<<endl;
	cout<<max<<endl;
	return 0;
}


2、将偶数个奇数个统一起来

如何统一,这是个问题?

我们可以这样,在每个字符之间插入一个特殊的字符

比如上面的字符串:abcgoogleaba。可以进行这样的操作:#a#b#c#g#o#o#g#l#e#a#b#a#

这样回文的字串就都是奇数的情况,就不需要考虑偶数的情况。

int getMaxHuiWenChar(char *p,int len)
{
	int nLen=2*len+3;
	char *str =new char[nLen];
	int i=0;
	int max;
	int j=0,x,y;
	str[0]='$';
	str[1]='#';
	for(;i<len;i++)//精华就是这里啦
	{
		str[i*2+2]=p[i];
		str[i*2+3]='#';
	}
	str[nLen-1]=0;

	for(i=0;i<nLen;i++)
	{
		cout<<str[i];
	}
	cout<<endl;

	for(i=1;i<nLen;i++)
	{
		for(j=0;i-j>=0&&i+j<nLen;j++)
		{
			if(str[i-j]!=str[i+j])
				break;
			else
			{
				if(j>max)
				{
					max=j;
					x=i-j;
					y=i+j;
				}
			}
		}
	}

	for(int k=x+1;k<=y-1;k+=2)//打印出回文
	{
		cout<<str[k];
	}
	return max;
}

输入:abcgottoglrcabac

3、上面的做法的时间复杂度依然不是很理想的

下面我们用更好的点做法O(n)

int getMaxHuiWenCharP(char *s,int len)
{
	int nLen=2*len+3;
	char *str =new char[nLen];
	int i=0;
	int max=0;
	str[0]='$';
	str[1]='#';
	for(;i<len;i++)
	{
		str[i*2+2]=s[i];
		str[i*2+3]='#';
	}
	str[nLen-1]=0;
	int *p=new int[nLen];//定义一个用于标记的int数组

	for(i=1;i<nLen;i++)
	{
		cout<<str[i];
		p[i]=0;
	}
	cout<<endl;

	int id=0;
	for(i=1; i<nLen; i++)
    {
        if( max > i )
            p[i] = MIN( p[2*id-i], p[id]+id-i );//这里定义一个MIN的宏
        else
            p[i] = 1;
        for(; str[i+p[i]] == str[i-p[i]]; p[i]++)
            NULL;
        if( p[i] + i > max )
        {
            max = p[i] + i;
            id = i;
        }
    }

	int mx=0;
	for(i=1;i<nLen;i++)
	{
		if(mx<p[i]-1)
			mx=p[i]-1;
	}
	return mx;
}

第二、网易游戏笔试题

根据上面提供的方式,大家先柔和下咯!

欢迎大家t提供更好的办法哈!
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值