zoukankan      html  css  js  c++  java
  • csu-1328 近似回文词 和 最长回文字符串

    原博文地址:http://blog.csdn.net/u012773338/article/details/39857997

    最长回文子串

    描述:输入一个字符串,求出其中最长的回文子串。子串的含义是:在原串连续出现的字符 串片段。回文的含义是:正着看和倒着看是相同的,如abba和abbebba。在判断是要求忽略所有的标点和空格,且忽略大小写,但输出时按原样输出(首 尾不要输出多余的字符串)。输入字符串长度大于等于1小于等于5000,且单独占一行(如果有多组答案,输出第一组)。

    输入 :每行有一个字符串。

    输出 :输出所要求的回文子串。

    样例输入:    Confuciuss say:Madam,I'm Adam.

    样例输出  :  Madam,I'm Adam

     

    思路:

    1,用gets或者fgets读入完整的一行,

    2,预处理构造一个新的字符串,不包含原来的标点符号,并且把所有字母变成大写。用s数组保存。

    3,枚举每个回文串的中间位置i,然后不断向外扩展,直到有字符不同,但是长度为奇数和偶数的处理方式是不一样的,比如aba,abba。

    回文串为奇数时,从第i个向左(i-j)向后(i+j)遍历,为偶数时,从第i个向左(i-j)向右(i+j+1)遍历。不想等就退出。

    4,不断更新最大回文串长度,并且用一个数组p保存最大回文串在原串的起始位置和结束位置。

    代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<ctype.h>
     4 #define MAXN 5000 + 10
     5 char buf[MAXN], s[MAXN];
     6 int p[MAXN];
     7 int main()
     8 {
     9     int n,m=0,maxn=0,x,y,i,j;
    10     fgets(buf,sizeof(s),stdin);//s肯定是一个字符数组。该调用从标准输入流stdin(也就是键盘输入)
    11     n=strlen(buf);            //读入 s 数组的大小(sizeof(s))再减 1 的长度的字符到 buf 所指的内存空间中(前提是buf已经申请好空间了)
    12     for(i=0;i<n;i++)
    13     {
    14         if(isalpha(buf[i])) //判断字符i是否是字母用到了isalpha这个函数
    15         {
    16             p[m]=i;     //把字母在原串的初始位置保存
    17             s[m++]=toupper(buf[i]); //转化成大写字母用s数组保存
    18         }
    19     }
    20     for(i=0;i<m;i++)
    21     {
    22         for(j=0;i-j>=0&&i+j<m;j++) //枚举奇数的回文串 注意下标的变换
    23         {
    24             if(s[i-j]!=s[i+j]) break;
    25             if(j*2+1>maxn) {maxn=j*2+1;x=p[i-j];y=p[i+j];}  //回文串的长度为2*j+1,比如aba,记录起始位置和终止位置
    26         }
    27         for(j=0;i-j>=0&&i+j+1<m;j++) //枚举偶数的回文串
    28         {
    29             if(s[i-j]!=s[i+j+1])break;
    30             if(j*2+2>maxn) {maxn=j*2+2;x=p[i-j];y=p[i+j+1];} //长度为2*j+2,比如abba,
    31         }
    32     }
    33     for(i=x;i<=y;i++)
    34         printf("%c",buf[i]); //输出最长回文串
    35     printf("
    ");
    36     return 0;
    37 }
    

    csu-1328 近似回文词

    1328: 近似回文词

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 312  Solved: 118
    [Submit][Status][Web Board]

    Description

    输入一行文本,输出最长近似回文词连续子串。所谓近似回文词是指满足以下条件的字符串:

    1. S以字母开头,字母结尾

    2. a(S)和b(S)最多有2k个位置不同,其中a(S)是S删除所有非字母字符并且把所有字母转化成小写之后得到的串,b(S)是a(S)的逆序串。

    比如当k=1时,Race cat是一个近似回文词,因为a(S)=racecat和b(S)=tacecar只有2个位置不同。

    Input

    输入包含不超过25组数据,每组数据包含两行。第一行是整数k(0<=k<=200),第二行为字符串S,包含至少一个字母但不超过1000个字符(换行符不算)。S只包含字符、空格和其他可打印字符(比如逗号,句号),并且不会以空白字符开头。

    Output

    对于每组测试数据,输出最长近似回文子串的长度和起始位置(S的第一个字符是位置1)。如果有多个最长近似回文子串解,起始位置应尽量小。

    Sample Input

    1
    Wow, it is a Race cat!
    0
    abcdefg
    0
    Kitty: Madam, I'm adam.
    

    Sample Output

    Case 1: 8 3
    Case 2: 1 1
    Case 3: 15 8
    

    HINT

     

    Source

    [Submit][Status][Web Board]

    跟上题的区别在于这里可以有2*k个字符不同,那处理的时候只要另外设置一个标志变量ans,当ans>k 就跳出即可,还要注意一些细节的处理,特别是枚举偶数的近似回文串的时候,如果j==0即没有满足题目条件的近似回文串,那么应该不能更新最大值,因为 ab不是回文串,最大长度只能是1。其他的就是一样。

    代码:

    #include<stdio.h>
    #include<string.h>
    #include<ctype.h>
    #define MAXN 1000 + 10
    char buf[MAXN], s[MAXN];
    int p[MAXN];
    int main()
    {
        int k,n,m,maxn,x,y,i,j,l=1,cas,start;
        while(scanf("%d",&k)!=EOF)
        {
            getchar();
            fgets(buf,sizeof(s),stdin);//s肯定是一个字符数组。该调用从标准输入流stdin(也就是键盘输入)
            n=strlen(buf);
            m=maxn=0;
            start=-1;        //读入 s 数组的大小(sizeof(s))再减 1 的长度的字符到 buf 所指的内存空间中(前提是buf已经申请好空间了)
            for(i=0;i<n;i++)
            {
                if(isalpha(buf[i])) //判断字符i是否是字母用到了isalpha这个函数
                {
                    p[m]=i;     //把字母在原串的初始位置保存
                    s[m++]=tolower(buf[i]); //转化成大写字母用s数组保存
                }
            }
            //s[m]=0;
            for(i=0;i<m;i++)
            {
                for(cas=j=0;i-j>=0&&i+j<m;j++) //枚举奇数的近似回文串
                {
                    if(s[i-j]!=s[i+j]) cas++;
                    if(cas>k) break;
                }
                j--;
                if(p[i+j]-p[i-j]+1>maxn) {maxn=p[i+j]-p[i-j]+1; start=p[i-j];}
                for(cas=j=0;i-j>=0&&i+j+1<m;j++) //枚举偶数的近似回文串
                {
                    if(s[i-j]!=s[i+j+1])cas++;
                    if(cas>k) break;
                }
                j--;
                if(j<=-1) continue;
                if(p[i+j+1]-p[i-j]+1>maxn) {maxn=p[i+j+1]-p[i-j]+1; start=p[i-j];}
            }
            printf("Case %d: %d %d
    ",l++,maxn,start+1);
     
        }
        return 0;
    }
  • 相关阅读:
    yocto/bitbake 学习资源
    QEMU/KVM学习资源
    ubuntu 中创建和删除用户
    git 重命名本地和远程分支
    Ubuntu 上搭建 FTP 服务器
    gdb 常见用法
    git log 显示与特定文件相关的 commit 信息
    基于 qemu system mode 运行 arm 程序
    基于 qemu user mode 运行 aarch64 程序
    checking in(airport)
  • 原文地址:https://www.cnblogs.com/lovychen/p/4458448.html
Copyright © 2011-2022 走看看