码迷,mamicode.com
首页 > 其他好文 > 详细

关于回文串的点点滴滴

时间:2015-07-19 21:32:46      阅读:118      评论:0      收藏:0      [点我收藏+]

标签:

  还是第一次发博文呢.嗯,最近在尝试每天做一道编程题,当然,我要求自己只能用C语言实现.一方面可增加自己对C函数库的熟悉程度,另一方面也想增加自身的编码经验.毕竟,感觉平时Code的时间严重不够.对于一个职业Coder来说这样肯定不太好嘛!


  好吧,回到正题吧.今天的题目内容很常规.就是判断用户输入的字符串是否是一个回文串,当然,难度稍微增加那么点,就是同时能够在一个字符串中找到所有的回文子串同时输出.想必,关于回文串的定义就没什么可说的了吧,比如"abba"就是个回文串,此外,还要能找出字符串"abc12321ddw"中的两个回文子串"12321"和"dd".自然,网上也有很多关于回文串判断的代码,但别人的代码终究不是自己写出来的,自然找不到感觉,所以就自己操练了一遍,好找一找感觉.


  好了,我将问题分成了两个部分来做:

  首先,我必须要能够判断一个字符串是一个回文串.那么回文串有什么特点呢?比如串"aba", "abba",仔细观察,会发现一些对称的特点.可以想象,手中有一张纸,我们现在要做的不过就是将这张纸给对折起来就好咯!所以,就有了下面的代码.我用它来判断字符串是否是回文串.当然,算法自然没什么优势,我对代码的追求是,首先它能运行,其次才是性能.

技术分享
 1 //函数功能:判断一个字符串是否是回文串.
 2 //入口参数:str--指向字符串的指针
 3 //返回:1--是回文串,0--不是回文串
 4 int IsPalindromeString(const char* str)
 5 {
 6     assert(str != NULL);
 7 //    printf("%s\n", str);
 8     int flag = 1;
 9     int len = strlen(str);
10     int i_begin = 0;
11     int i_end = len - 1;
12     //如果长度为1,则fei回文串.
13     if (len <= 1)
14     {
15         flag = 0;
16     }
17     else
18     {
19     //想象将字符串进行折叠,若发现某个字符不重合,则判断一定不是回文串,否则是个回文串.
20         for (; i_begin <= i_end; i_begin++, i_end--)
21         {
22             if (tolower(str[i_begin]) != tolower(str[i_end]))
23             {
24                 flag = 0;
25                 break;
26             }
27         }
28     }
29     return flag;
30 }
查看代码

  好了,继续往下分析.我们以这样的一个字符串为例:"acd12321dfe",显然,我们很容易看出来中间的"12321"是个回文子串,但计算机可没那么聪明,那该怎么做呢?自然,我还是用了比较笨的办法咯.用两个游标i和j.这两个游标开始分别指向串首和串尾.然后,我们将从i开始到j结束的所有字符提取到一个临时串中并判断是否是回文串.通过不断地移动最终把所有的回文子串查找出来.

  自然而然地,我们显然要有个能够提取子串函数来完成字符串提取工作,于是就有了下面的函数咯,注意,我将一句话中可能存在的空格,标点符号等给忽略了,比如经典的回文语句"Able was I ere I saw Elba"很显然是个回文语句,所以,不能因为其中的空格或者大小写问题就造成误判:

技术分享
 1 //函数功能:从源串中提取指定长度的子串到目的缓冲区保存
 2 //入口参数:dest--指向目的缓冲区的指针, src--指向源串的指针,start--起始位置,end--结束位置
 3 //返回:void
 4 void SubString(char* dest, const char* src, int start, int end)
 5 {
 6     assert(dest != NULL && src != NULL);
 7     //下面是一种比较笨的复制字符串的方法.
 8     //,.?! will not copy.
 9     int i = 0, j = start;
10     while (j <= end)
11     {
12         if (src[j] ==  || src[j] == , || src[j] == . ||
13             src[j] == ? || src[j] == ! || src[j] == \‘)
14         {
15             j++;
16         }
17         else
18         {
19             dest[i++] = src[j++];
20         }
21     }
22 }
查看代码

  想一想,现在我们还需要一个查找一个字符串所有回文子串的函数了.于是便有了下面的函数.它用来接受用户输入的字符串,并将字符串中所有能构成的回文子串给打印出来.

 

  代码中,使用了malloc()函数申请了临时存储空间,用来存放每次用于测试的子串.算法估计算不上优,但是可正常工作了.

技术分享
 1 //函数功能:查找一个字符串中所有的回文串并且打印出来
 2 //入口参数:str(指向一个字符串的指针)
 3 //返回:void
 4 void FindPalindromeSubString(const char* str)
 5 {
 6     assert(str != NULL);
 7     int len = strlen(str);
 8     int i = 0, j = 0, tmpPos = i, k = 0;
 9     //申请开辟一块缓冲区,用来存放测试串.
10     char* pBuff = (char*)malloc((len + 1) * sizeof(char));
11     if (pBuff == NULL)
12         return;
13 
14     for (i=0; i<len; i++)
15     {
16         for (j=(len - 1); j>=tmpPos; j--)
17         {
18             if (str[i] == str[j])
19             {
20                 memset(pBuff, \0, (len + 1) * sizeof(char));
21                 SubString(pBuff, str, i, j);
22                 if (IsPalindromeString(pBuff))
23                 {
24                     //当查找到回文子串时就打印出来.
25                     printf("#%d, length=%d: %s\n", ++k, (int)strlen(pBuff), pBuff);
26                     tmpPos = j + 1;
27                 }
28             }
29         }
30     }
31 
32     if (k < 1)
33     {
34         printf("没有找到回文子串.\n");
35     }
36     free(pBuff);
37     pBuff = NULL;
38 }
查看代码

  好了,我们来看看main函数的实现代码吧,然后结束我们这个枯燥的话题吧^_^

技术分享
 1 int main(void)
 2 {
 3     char ch[MAXLEN] = {\0};
 4     while (1)
 5     {
 6         memset(ch ,\0, MAXLEN * sizeof(char));
 7         printf("请输入字符串,程序将会输出所有的回文子串:\n");
 8         fgets(ch, MAXLEN * sizeof(char), stdin);
 9         FindPalindromeSubString(ch);
10         printf("\n");
11     }
12     return 0;
13 }
查看代码

  

  总结下,以上代码所使用的算法并非最优解,只代表我个人的解题思路,如果希望能找到更好的算法,CSDN的博客上也可以搜索到的.

 

  上面的代码,我在gcc4.8.2下编译并正常运行,来看看在Ubuntu14.04下测试的结果吧!

技术分享


  顺便给Ubuntu做个广告吧!^_^,Good.

技术分享

更改日志:

2014-4-28日,修改了FindPalindromeSubString()函数.第一,增加了一个判断,防止无意义的拷贝;第二,防止因为有类似"abcdcbabcdc"这样的重叠回文串判断错误!

  

版权声明:本文为博主原创文章,未经博主允许不得转载。

 

关于回文串的点点滴滴

标签:

原文地址:http://www.cnblogs.com/chriscabin/p/4659343.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!