USACO Calf Flac

本文介绍了一种寻找给定字符串中最长回文子串的方法,包括考虑奇数和偶数长度的回文串,并提供了两种不同的C++实现方案。

1、这道题真是相当麻烦,无法预处理,而且数据还可能是好多行。

2、刚开始我忽略了回文串可以是偶数,所以WA。

3、代码比较乱。注意数组很容易越界,要控制边界。

/*
ID:mrxy564
PROG:calfflac
LANG:C++
*/
#include<cstdio>
#include<cstring>
#include<cctype>
using namespace std;
char s[20010],ch;
int len,cnt,left,right,max,maxi,num;
int main(){
    freopen("calfflac.in","r",stdin);
    freopen("calfflac.out","w",stdout);
    len=0;
    while((ch=getchar())!=EOF) s[len++]=ch;
         max=0;
         for(int i=0;i<len-1;i++){
             left=right=i;cnt=0;
             while(1){
               while(!isalpha(s[left])&&left>=0) left--;
               while(!isalpha(s[right])&&right<len) right++;
               if(left<0||right>=len-1) break;
               else{
                   if(tolower(s[left])==tolower(s[right])){
                       cnt++;
                       left--;
                       right++;
                       if(cnt>max) {max=cnt;maxi=i;}
                   }
                   else break;
               }
             }
         }
         num=max;
         bool flag=false;
         for(int i=0;i<len-2;i++){
             left=i;
             if(!isalpha(s[left])) continue;
             right=i+1;
             while(right<len-1&&!isalpha(s[right])) right++;
             cnt=0;
             while(1){
               while(!isalpha(s[left])&&left>=0) left--;
               while(!isalpha(s[right])&&right<len) right++;
               if(left<0||right>=len-1) break;
               else{
                   if(tolower(s[left])==tolower(s[right])){
                       cnt++;
                       left--;
                       right++;
                       if(cnt*2>2*max-1) {flag=true;max=cnt;maxi=i;}
                   }
                   else break;
               }
             }
         }
         int p=maxi;
         for(int i=0;i<max-1;i++){
             p--;
             while(!isalpha(s[p])) p--;
         }
        if(flag){
           printf("%d\n",max*2);
           max=max*2;
           while(max--){
             printf("%c",s[p++]);
             if(max==0) break;
             while(!isalpha(s[p]))
                 printf("%c",s[p++]);
           }
        }
        else{
          printf("%d\n",2*max-1);
          max=max*2-1;
          while(max--){
             printf("%c",s[p++]);
             if(max==0) break;
             while(!isalpha(s[p]))
                 printf("%c",s[p++]);
          }
        }
         printf("\n");
         return 0;
}
官方题解:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ctype.h>

char fulltext[21000];
char text[21000];

char *pal;
int pallen;

void
findpal(void)
{
    char *p, *fwd, *bkwd, *etext;
    int len;

    etext = text+strlen(text);
    for(p=text; *p; p++) {
	/* try palindrome with *p as center character */
	for(fwd=bkwd=p; bkwd >= text && fwd < etext && *fwd == *bkwd;
				fwd++, bkwd--)
			;
	bkwd++;
	len = fwd - bkwd;
	if(len > pallen) {
	    pal = bkwd;
	    pallen = len;
	}

	/* try palindrome with *p as left middle character */
	for(bkwd=p, fwd=p+1;
	          bkwd >= text && fwd < etext && *fwd == *bkwd; fwd++, bkwd--)
			;
	bkwd++;
	len = fwd - bkwd;
	if(len > pallen) {
	    pal = bkwd;
	    pallen = len;
	}
    }
}

void
main(void)
{
    FILE *fin, *fout;
    char *p, *q;
    int c, i, n;

    fin = fopen("calfflac.in", "r");
    fout = fopen("calfflac.out", "w");
    assert(fin != NULL && fout != NULL);

    /* fill fulltext with input, text with just the letters */
    p=fulltext;
    q=text;
    while((c = getc(fin)) != EOF) {
	if(isalpha(c))
	    *q++ = tolower(c);
	*p++ = c;
    }
    *p = '\0';
    *q = '\0';

    findpal();

    fprintf(fout, "%d\n", pallen);

    /* find the string we found in the original text
       by finding the nth character */
	n = pal - text;
    for(i=0, p=fulltext; *p; p++)
	if(isalpha(*p))
	    if(i++ == n)
		break;
    assert(*p != '\0');

    /* print out the next pallen characters */
    for(i=0; i<pallen && *p; p++) {
	fputc(*p, fout);
	if(isalpha(*p))
	    i++;
    }
    fprintf(fout, "\n");

    exit(0);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值