算法竞赛入门经典: 第三章 数组和字符串 3.5回文串

/*
回文串:
输入一个字符串,求出其中最长的回文串。子串:在原串中连续出现的字符串片段。忽略标点和空格,大小写
输入字符串长度不超过5000,且占据单独一行。若有多个最长回文串,则输出起始位置最靠左的
输入:
Confuciuss say:Madam.I'm Adam.
输出:
Madam,I'm Adam
*/

/*
关键:
1printf输出到屏幕,fprintf输出到文件,sprintf输出到字符串,sprintf需要确保字符串足够大:字符个数+1(保证结束符)
2strlen求得是实际长度。声明20长度,实际"2357",那么长度是5,包含结束符,后面字符不确定
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>//isalpha函数需要用到

#define MAXSIZE 5000+1

/*
void maxEchoStr(char* str)
{
	int iMaxLen = 0;
	bool ok = true;
	int iLen = strlen(str);
	int k = 0,i,j;
	while(k < iLen)
	{
		for(i = k,j = iLen ; i <= j ; i++,j--)
		{
			if(str[i] != str[j])
			{
				ok = false;
			}
		}
		if(ok)
		{
			iMaxLen = j - i + 1;
		}
	}
}
*/

/*
1用fgets函数来读取一行内容,改为文件操作
2预处理设置一个字符串过滤标点,并转化成大写
3判断回文时,设置起点i,终点j,最长回文长度max,最长回文起始位置begin
4还需要设置一个数组保存起始位置,为原样输出做准备iPosArr[k] = c;
5 fgets(cBuf,MAXSIZE,fin);//char* fgets(char* buf,size_t maxsize,FIEL* stream),读取maxsize-1个字符存储到buf中,成功返回该字符串
6 if(isalpha(cBuf[c]))//#include <ctype.h>,int isalpha(int ch):字符返回非零值
7 for(i = 0 ; i < iStrLen ; i++)//回文串中间节点,
  for(j = 0; i - j >= 0 && i + j < iStrLen ; j++)//对奇数进行回文串进行判断,if( 2*j + 1 > iMaxLen)//j作为回文串单边长度,因为有中间节点,所以是2*j+1,if( 2*j + 1 > iMaxLen)//j作为回文串单边长度,因为有中间节点,所以是2*j+1
  for( j = 0 ; i - j >= 0 && i + j + 1 < iStrLen ; j++)//针对回文串偶数情况,if(str[i - j] != str[i + j + 1])//对相邻的情况进行判断
  
*/

void maxEchoStr()
{
	FILE* fin;
	fin = fopen("input.txt","rb");
	//fout = fopen("output.txt","wb");
	char cBuf[MAXSIZE];
	int iPosArr[MAXSIZE];
	fgets(cBuf,MAXSIZE,fin);//char* fgets(char* buf,size_t maxsize,FIEL* stream),读取maxsize-1个字符存储到buf中,成功返回该字符串
	char str[MAXSIZE];
	int k = 0;
	int iLen = strlen(cBuf);
	//去除标点符号+转换为大写
	for(int c = 0 ; c < iLen ; c++)
	{
		if(isalpha(cBuf[c]))//#include <ctype.h>,int isalpha(int ch):字符返回非零值
		{
			iPosArr[k] = c;
			str[k++] = toupper(cBuf[c]);
		}
	}
	str[k] = '\0';
	int iMaxLen = 0;
	int iStrLen = strlen(str);
	int i,j,x,y;
	for(i = 0 ; i < iStrLen ; i++)//回文串中间节点
	{
		for(j = 0; i - j >= 0 && i + j < iStrLen ; j++)//对奇数进行回文串进行判断
		{
			if(str[i - j] != str[i + j])//以中间节点向两边扩展
			{
				break;
			}
			if( 2*j + 1 > iMaxLen)//j作为回文串单边长度,因为有中间节点,所以是2*j+1
			{
				iMaxLen = 2*j + 1;
				x = iPosArr[i - j];
				y = iPosArr[i + j];
			}
		}
		for( j = 0 ; i - j >= 0 && i + j + 1 < iStrLen ; j++)//针对回文串偶数情况
		{
			if(str[i - j] != str[i + j + 1])//对相邻的情况进行判断
			{
				break;
			}
			if(j*2 + 2 > iMaxLen)//当j=0的时候,长度为2,所以是2*j+2
			{
				iMaxLen = j*2 + 2;
				x = iPosArr[i - j];
				y = iPosArr[i + j + 1];
			}
		}
	}
	fclose(fin);
	//fclose(fout);
	for(int l = x; l <= y ;l++)
	{
		printf("%c",cBuf[l]);
	}
	printf("\n");
//	return echoStr;
}

void echoStr()
{
	char buf[MAXSIZE],str[MAXSIZE];
	FILE* fin;
	fin = fopen("input.txt","rb");
	fgets(buf,MAXSIZE,fin);
	int iPosArr[MAXSIZE];
	int x,y,iMaxLen = 0;
	//预处理
	int k = 0;
	for(int i = 0 ; i < strlen(buf); i++)
	{
		if(isalpha(buf[i]))
		{
			iPosArr[k] = i;
			str[k++] = toupper(buf[i]);
		}
	}
	for(int p = 0 ; p < k; p++)//中间位置
	{
		for(int q = 0 ; p - q >= 0 && p + q <k ; q++)//检测奇数回文串
		{
			if(str[p -q] != str[p + q])
			{
				break;
			}
			if(2*q + 1 > iMaxLen)
			{
				iMaxLen = 2*q + 1;
				x = iPosArr[p - q];
				y = iPosArr[p + q];
			}
		}
		for(int q = 0 ; p - q >= 0 && p + q + 1 < k ; q++)//检测偶数回文串
		{
			if(str[p-q] != str[p+q+1])
			{
				break;
			}
			if(2*q + 2 > iMaxLen)
			{
				iMaxLen = 2*q + 2;
				x = iPosArr[p - q];
				y = iPosArr[p + q + 1];
			}
		}
	}
	for(int c = x ; c <= y ;c++)
	{
		printf("%c",buf[c]);
	}
	printf("\n");
	fclose(fin);
}

int main(int argc,char* argv[])
{
	char str[MAXSIZE];
	//char sBuf[MAXSIZE];
	//scanf("%s",str);

	maxEchoStr();
	echoStr();
	system("pause");
	return 0;
}

你可能感兴趣的:(算法竞赛入门)