POJ 1590 -- 回文词
来源:互联网 发布:php获取url参数 编辑:程序博客网 时间:2024/05/16 12:16
一、题目
1590题,要求判断一个字符串是否是回文串或镜像串。回文串,就是将字符串倒序排列,与原串相同,如abba和madam;镜像串,先将串中每个字符做镜像,然后将字符串倒序排列后,与原串相同,如2S(2的镜像是S,S的镜像是2),以及3AIAE(3、E互为镜像)。并非每个字符镜像后都是合法字符,如下图,空白代表非法字符。
题目要求:输入每行包含一个字符串(保证只有上图中Character列的字符,即大写字母与数字),判断它是否为回文串或镜像串(共4种组合),每组数据后输出一个空行。
样例输入:
NOTAPALINDROME
ISAPALINILAPASI
2A3MEAS
ATOYOTA
样例输出:
NOTAPALINDROME – is not a palindrome.
ISAPALINILAPASI – is a regular palindrome.
2A3MEAS – is a mirrored string.
ATOYOTA – is a mirrored palindrome.
二、我的思路
我的思路非常stupid:
判断回文:使用两个指针分别指向输入字符串的第一个和最后一个字符,比较指针内容,若相同,则同时向中间移一格,继续比较,如此比了移,移了比,直到两个指针内容不等(不是回文),或头指针已经在尾指针右边了(是回文),结束。
判断镜像:用一个含21个元素的全局字符数组,将上图中拥有合法镜像字符的21个字符置于数组中,扫描一遍字符串,查看是否包含非法镜像字符,若有,则不是镜像,若无,则是。(注意,我忽略了镜像串也需要倒序相等的特点)
于是,写成代码如下:
#include <stdio.h>char mirror[21] = {'A','E','H','I','L','J','M','O','S','T','U','V','W','X','Y','Z','1','2','3','5','8'};bool isMirror(char c){ for(int i=0; i<21; i++){ if(c==mirror[i]) return true; } return false;}int main(){ char input[200]; while(scanf("%s", input) == 1){ char* head = input; char* tail = input; int len = 0; while(*tail != '\0'){ tail++; len++; } tail = tail - 1; bool is_par = true; bool is_mir = true; //if the string is a palindrom or a mirror string for(int i=0; i<len; i++){ if(i<(len/2) && *head != *tail) is_par = false; if(!isMirror(*head)) is_mir = false; head++; tail--; } //output if(is_par && is_mir) printf("%s -- is a mirrored palindrome.\n\n", input); else if(is_par && !is_mir) printf("%s -- is a regular palindrome.\n\n", input); else if(!is_par && is_mir) printf("%s -- is a mirrored string.\n\n", input); else printf("%s -- is not a palindrome.\n\n", input); } return 0;}
注意,在我没有实现镜像串的倒序相等特点的情况下,提交至POJ,通过。估计它只看题目中给的4个样例的结果,完全符合就行了。
顺便提一嘴,刷题中,输出的格式异常重要,一个字符都不能错,比如这里最后的“.”,以及输出一行字符以后还得空一行等。所以,当它报出“Wrong Answer”的错误时,首先检查是否输出格式有问题。
三、书上思路
刘汝佳的《算法竞赛入门经典》,由于我没搞过ACM,真是相见恨晚,里面专业而细致的描述、简短而有力的代码,让初爱编程者爱不释手。
来看书中49页对此题的解法:
#include <stdio.h>#include <string.h>#include <ctype.h>const char* mir = "A 3 HIL JM O 2TUVWXY51SE Z 8 ";const char* msg[] = {"not a palindrome.", "a regular palindrome.", "a mirrored string.", "a mirrored palindrome."};char mirrored(char c){ if(isalpha(c)) return mir[c - 'A']; return mir[c - '0' + 25];}int main(){ char s[200]; while(scanf("%s", s)==1){ int len = strlen(s); int p = 1, m = 1; for(int i=0; i<(len+1)/2; i++){ if(s[i] != s[len-i-1]) p = 0;// is not a palindrome if(mirrored(s[i]) != s[len-1-i]) m = 0;//is not a mirrored string } printf("%s -- is %s\n\n", s, msg[2*m+p]); } return 0;}
对于编程渣的我来说,其中的亮点有:
- 开头定义了两个常量数组,注意,尽量用const来声明常数(《算法竞赛入门经典》P6 提示1-7);
- 常量字符串数组msg[],以及遥相辉映地最后printf那句代码,简直不能再机智,所以在程序中用int而非bool来表示“是”“否”;
- 使用isalpha()函数来判断字符是否为英文字母,类似地还有idigit(十进制数字)、isprint(可打印字符,其ASCII码值大于 0x1f(除0x7f(DEL)外))、toupper和tolower则用来转换字母大小写,这些都定义在ctype.h中;
- mirrored函数中的两个return,是熟练运用ASCII码计算的表现,多么简洁有力;
- 将scanf()放在while的条件中,既能输入,又能循环,一举两得;
- for循环中,就用s[i]、s[len-1-i]就表示了头尾对称的两个字符,哪儿像我傻不拉几还去定义两个指针。
哈哈,看高手代码就是开心!
- POJ 1590 -- 回文词
- ACM POJ 1159 Palindrome 回文词
- 回文串 poj 1159
- poj 4067: 回文数字
- POJ 回文素数
- poj 3280 dp回文
- Poj:3974 回文串
- POJ 3974 Palindrome 回文串
- poj 1159 回文串问题
- poj 1221 单峰回文数
- POJ 3280 最小回文代价
- poj 3974 Palindrome 最长回文
- poj 1159(回文串dp)
- Poj 3974 回文串--Manacher
- poj 1153 Palindrome(回文字符串)
- POJ 1159--Palindrome(回文序列)
- poj 3280-回文串-DP
- POJ-1159 最长回文字符串
- 收集整理的shell游戏
- 【数据结构】中平衡搜索树的旋转方式解析
- Linux内核分析之简析加载和启动一个可执行程序
- Ant1.8.2 Jdk7 Dockerfile
- 1038. 统计同成绩学生(20)
- POJ 1590 -- 回文词
- new、引用
- sealed(C# 参考)
- 工作思想总结
- bzoj2190 [SDOI2008]仪仗队
- python3和2共存
- php,java实现组合模式
- JAVA面向对象
- Mycat生产实践---Mycat实施指南