《算法竞赛入门经典》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的长度,包含文件结束符‘\0‘
 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\n",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的长度,包含文件结束符‘\0‘
 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("\n");
 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     */  
时间: 2024-10-13 14:50:24

《算法竞赛入门经典》3.3最长回文子串的相关文章

最长回文子串(转自:hihoCoder)

#1032 : 最长回文子串 时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:"小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?" 小Ho奇怪的问道:"什么叫做最长回文子串呢?" 小Hi回答道:"一个字符串中连续的一

#1032 : 最长回文子串

描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?” 小Ho奇怪的问道:“什么叫做最长回文子串呢?” 小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往前读一模一样的字符串,所以最长回文子串的意思就是这个字符串中最长的身

hiho一下 第一周 最长回文子串

时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在这些字符串中找到它们每一个的最长回文子串呢?” 小Ho奇怪的问道:“什么叫做最长回文子串呢?” 小Hi回答道:“一个字符串中连续的一段就是这个字符串的子串,而回文串指的是12421这种从前往后读和从后往

求最长回文子串,O(n)复杂度

最长回文子串问题-Manacher算法 最长回文串问题是一个经典的算法题. 0. 问题定义 最长回文子串问题:给定一个字符串,求它的最长回文子串长度. 如果一个字符串正着读和反着读是一样的,那它就是回文串.下面是一些回文串的实例: 12321 a aba abba aaaa tattarrattat(牛津英语词典中最长的回文单词) 1. Brute-force解法 对于最长回文子串问题,最简单粗暴的办法是:找到字符串的所有子串,遍历每一个子串以验证它们是否为回文串.一个子串由子串的起点和终点确定

《算法竞赛入门经典(第二版)》pdf

下载地址:网盘下载 内容简介  · · · · · · <算法竞赛入门经典(第2版)>是一本算法竞赛的入门与提高教材,把C/C++语言.算法和解题有机地结合在一起,淡化理论,注重学习方法和实践技巧.全书内容分为12 章,包括程序设计入门.循环结构程序设计.数组和字符串.函数和递归.C++与STL入门.数据结构基础.暴力求解法.高效算法设计.动态规划初步.数学概念与方法.图论模型与算法.高级专题等内容,覆盖了算法竞赛入门和提高所需的主要知识点,并含有大量例题和习题.书中的代码规范.简洁.易懂,不

《算法竞赛入门经典》动态规划复习

codevs 4979 数塔 1 #define N 100 2 #include<iostream> 3 using namespace std; 4 #include<cstdio> 5 int a[N][N],b[N][N],n; 6 int main() 7 { 8 scanf("%d",&n); 9 for(int i=1;i<=n;++i) 10 for(int j=1;j<=i;++j) 11 { 12 scanf("

算法竞赛入门经典+挑战编程+USACO

下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发.   一.UVaOJ http://uva.onlinejudge.org  西班牙Valladolid大学的程序在线评测系统,是历史最悠久.最著名的OJ.   二.<算法竞赛入门经典> 刘汝佳  (UVaOJ  351道题)  以下部分内容摘自:http://sdkdacm.5d6d.com/thread-6-1-1.html   "AO

(Step1-500题)UVaOJ+算法竞赛入门经典+挑战编程+USACO

下面给出的题目共计560道,去掉重复的也有近500题,作为ACMer Training Step1,用1年到1年半年时间完成.打牢基础,厚积薄发. 一.UVaOJ http://uva.onlinejudge.org 西班牙Valladolid大学的程序在线评测系统,是历史最悠久.最著名的OJ. 二.<算法竞赛入门经典> 刘汝佳  (UVaOJ  351道题)  以下部分内容摘自:http://sdkdacm.5d6d.com/thread-6-1-1.html “AOAPC I”是刘汝佳(大

《算法竞赛入门经典第二版》 P35 习题2-4 子序列的和(subsequence)

/* <算法竞赛入门经典第二版> P35 习题2-4: 输入两个正整数 n < m < 10^6,输出 (1/n)^2 + 1/(n+1)^2 +……+ 1/m^2,保留5位小数. 输入包含多组数据,结束标志为 m=n=0. 有错欢迎指出^_^ */ #include<stdio.h> int main() { int m,n,i,j=1; while(scanf("%d%d",&m,&n) != EOF) { double sum