zoukankan      html  css  js  c++  java
  • 《算法竞赛入门经典》3.3最长回文子串

      1     //例题3-4  
      2     /*  
      3     * 输入一个字符串,求出其中最长的回文子串。子串的含义是:在原串中连续出现的字符串片段。 
      4     *回文的含义是:正看着和倒看着相同,如abba和yyxyy。在判断时,应该忽略所有标点符号和空格 
      5     *且忽略大小写,但输出应保持原样(在回文串的首部和尾部不要输出多余字符)。输入字符长度不超过5000 
      6     *且占据单独的一行。应该输出最长回文串,如果有多个,输出起始位置最靠左的。 
      7     *样例输入:Confuciuss say:Madam,I'm Adam. 
      8     *样例输出:Madam,I'm Adam 
      9     */  
     10       
     11     //程序3-5 最长回文子串(1)  
     12     #include<stdio.h>  
     13     #include<string.h>  
     14     #include<ctype.h>     //用到isalpha、touuper等工具  
     15     #define MAXN 5000+10  
     16     char buf[MAXN],s[MAXN];  
     17     int main()  
     18     {  
     19         int n,m=0,max=0;  
     20         int i,j,k;  
     21         fgets(buf,sizeof(s),stdin);     //从标准输入流中读取sizeof(s)-1个字符并且把他们转储到buf中  
     22         n=strlen(buf);                  //获取buf的长度,包含文件结束符''  
     23         for(i=0;i<n;i++)    
     24                                 //构造一个新的字符串,把标点符号过滤掉,随便把小写字母变为大写  
     25             if(isalpha(buf[i])) s[m++]=toupper(buf[i]);  
     26         for(i=0;i<m;i++)     //其中m是新字符串s的长度  
     27             for(j=i;j<m;j++)  
     28             {  
     29                 int ok=1;  
     30                 for(k=i;k<=j;k++)    //判断s[i..j]是否为回文串  
     31                     if(s[k]!=s[i+j-k]) ok=0;      
     32                 if(ok && j-i+1>max) max=j-i+1;   //保存当前发现的最长回文串  
     33             }  
     34             printf("max=%d
    ",max);  
     35             return 0;  
     36     }  
     37       
     38       
     39     //程序3-5 最长回文子串(2)  
     40     #include<stdio.h>  
     41     #include<string.h>  
     42     #include<ctype.h>     //用到isalpha、touuper等工具  
     43     #define MAXN 5000+10  
     44     char buf[MAXN],s[MAXN];  
     45     int p[MAXN];            //增设数组p,用于保存s[i]在buf中的位置  
     46     int main()  
     47     {  
     48         int n,m=0,max=0,x,y;  
     49         int i,j,k;  
     50         fgets(buf,sizeof(s),stdin); //从标准输入流中读取sizeof(s)-1个字符并且把他们转储到buf中  
     51         n=strlen(buf);              //获取buf的长度,包含文件结束符''  
     52         for(i=0;i<n;i++)  
     53             if(isalpha(buf[i]))     //构造一个新的字符串,把标点符号过滤掉,随便把小写字母变为大写  
     54                 {  
     55                     p[m]=i;         //保存s[m]在buf的位置  
     56                     s[m++]=toupper(buf[i]);   
     57             }  
     58             for(i=0;i<m;i++)     //遍历字符串s,以i为"中间"位置,然后根据j的值不断向两边扩展  
     59             {                       //这个for循环遍历的子串长度为奇数  
     60                 for(j=0;i-j>=0 && i+j<m; j++) //注意i和j的关系:i-j>=0表示i到j的距离不能上溢  
     61                                                 //i+j<m表示i再加j个位置没有超过字符串s的总长  
     62                 {  
     63                     if(s[i-j]!=s[i+j]) break;   //如果以i为中间点,左边i-j个点字符跟右边i+j个点不同,跳出循环  
     64                     if(j*2+1>max)                //因为子串的长度为奇数,所以子串的长度应该等于j*2+1(j为以i为中心,往两边的距离)  
     65                     { max=j*2+1; x=p[i-j];y=p[i+j]; } //保存当前最长回文子串长度,记录子串范围  
     66                 }  
     67                 for(j=0;i-j>=0 && i+j+1<m; j++)//这个for循环遍历的子串长度为偶数,  
     68                     //中间点i取子串长度的中点,导致两边长度不均,右边的距离应该再加1  
     69                 {  
     70                     if(s[i-j]!=s[i+j+1]) break;  
     71                     if(j*2+2>max)            
     72                     { max=j*2+2; x=p[i-j]; y=p[i+j+1]; }  
     73                 }  
     74             }  
     75             for(i=x;i<=y;i++)    //把最长回文子串输出  
     76                 printf("%c",buf[i]);  
     77             printf("
    ");  
     78             return 0;  
     79     }  
     80       
     81       
     82     /*样例输入:Confuciuss say:Madam,I'm Adam. 
     83     *样例输出:Madam,I'm Adam 
     84     * 
     85     //分析得出最长回文子串的过程 
     86     *(1)    for(i=0;i<m;i++)     //遍历字符串s,以i为"中间"位置,然后根据j的值不断向两边扩展 
     87             {                       //这个for循环遍历的子串长度为奇数 
     88     *(2)        for(j=0;i-j>=0 && i+j<m; j++) //注意i和j的关系:i-j>=0表示i到j的距离不能上溢 
     89                                                 //i+j<m表示i再加j个位置没有超过字符串s的总长 
     90                 { 
     91                     if(s[i-j]!=s[i+j]) break;   //如果以i为中间点,左边i-j个点字符跟右边i+j个点不同,跳出循环 
     92                     if(j*2+1>max)                //因为子串的长度为奇数,所以子串的长度应该等于j*2+1(j为以i为中心,往两边的距离) 
     93                     { max=j*2+1; x=p[i-j];y=p[i+j]; } //保存当前最长回文子串长度,记录子串范围 
     94                 } 
     95     *(3)        for(j=0;i-j>=0 && i+j+1<m; j++)//这个for循环遍历的子串长度为偶数, 
     96                     //中间点i取子串长度的中点,导致两边长度不均,右边的距离应该再加1 
     97                 { 
     98                     if(s[i-j]!=s[i+j+1]) break; 
     99                     if(j*2+2>max)           
    100                     { max=j*2+2; x=p[i-j]; y=p[i+j+1]; } 
    101                 } 
    102             } 
    103     *字符串s="CONFUCIUSSSAYMADAMIMADAM" 
    104     *字符串长度m=24 
    105     *第一个for循环循环到i=18的时候 
    106     *也就是遍历到s[18]位置上,这时s[18]='I' 
    107     *接着进行内部循环,执行第二个循环体,开始以I为中心点,向两边扩展 
    108     *i=18,j=0,满足条件,执行if语句,s[i-j]=I,s[i+j]=I,s[i-j]=s[i+j]不满足条件 
    109     *执行下一条if语句,判断j*2+1是否大于max,0*2+1<max=5,不满足条件,因为之前第一个回文子串是MADAM,长度为5 
    110     *j=1;s[i-j]=M,s[i+j]=M;不满足条件 
    111     *j*2+1<max,max=5,p[i-j]=17,p[i+j]=19 
    112     *j=2;s[i-j]=A;s[i+j]=A; 
    113     *j*2+1=max,max=5,p[i-j]=16,p[i+j]=20 
    114     *j=3;s[i-j]=D;s[i+j]=D; 
    115     *j*2+1>max,max=7,p[i-j]=15,p[i+j]=21 
    116     *j=4;s[i-j]=A;s[i+j]=A; 
    117     *j*2+1>max,max=9,p[i-j]=14,p[i+j]=22 
    118     *j=5;s[i-j]=M;s[i+j]=M; 
    119     *j*2+1>max,max=11,p[i-j]=13,p[i+j]=23,x=13,y=23 
    120     *j=6;i+j>m,结束本次循环 
    121     *继续执行下一个for语句 
    122     *i=18,j=0,满足循环条件,执行循环体 
    123     *s[i-j]!=s[i+j+1];满足条件,break跳出循环 
    124     *到此最长的回文子串已经得出来了,不过还要继续遍历字符串,直到结束为止 
    125     *最后结果:Madam,I'm Adam 
    126     */  
    亲爱的读者:如果觉得本文对你有所帮助,请点击推荐,分享给其他人!
  • 相关阅读:
    mysql的安装
    一个电脑登录多个微信
    项目工程构建
    MYSQL 添加字段
    Centos 搭建maven私服
    Nacos 动态刷新@RefreshScope
    Cookie & Session
    阿里蚂蚁 笔试题
    springboot 将配置文件中的配置读取为properties配置类
    .Net Gacutil工具(全局程序集缓存工具)使用教程
  • 原文地址:https://www.cnblogs.com/zhuangwei/p/5243608.html
Copyright © 2011-2022 走看看