字符串类习题、面试题具体解释(第二篇)
第一篇链接:字符串类习题、面试题具体解释(第一篇)
6题:回文串(竞赛基础题)
输入一个字符串,求出其最长回文子串。子串的含义是:在原串中连续出现的字符串片段。回文的含义是:正着看和倒着看同样,如abba和yyxyy。在推断时,应该忽略全部标点符号和空格,且忽略大写和小写,但输出应保持原样(在回文串的首部和尾部不要输出多余字符)。输入字符串长度不超过5000,且占领单独一行。应该输出最长的回文串,假设有多个,输出起始位置最靠左的。
例子输入:Confuciuss say: Madam, I’m Adam.
例子输出:Madam,I’m Adam
方法1:枚举回文串的起点和终点。
#include <stdio.h> #include <ctype.h> #include <string.h> #define MAXN 5000 + 10 char buf[MAXN], s[MAXN]; int p[MAXN]; int main(void) { int n, m = 0, max = 0, x, y; int i, j, k, ok; fgets(buf, sizeof(buf), stdin); n = strlen(buf); for (i = 0; i < n; i++) { if (isalpha(buf[i])) { p[m] = i; //保存字符的实际位置 s[m++] = toupper(buf[i]); //保存为大写字母 } } for (i = 0; i < m; i++) //枚举回文串起始位置 { for (j = i; j < m; j++) //枚举回文串终止位置 { ok = 1; for (k = i; k <= j; k++) { if (s[k] != s[i + j - k]) ok = 0; } if (ok && j - i + 1 > max) { max = j - i + 1; x = p[i]; y = p[j]; } } } for (i = x; i <= y; i++) { printf("%c", buf[i]); } printf("\n"); return 0; }方法2:枚举回文串的中间位置。
#include <stdio.h> #include <string.h> #include <ctype.h> #define MAXN 5000 + 10 char buf[MAXN], s[MAXN]; int p[MAXN]; int main(void) { int n, m = 0, max = 0, x, y; int i, j; fgets(buf, sizeof(buf), stdin); n = strlen(buf); for (i = 0; i < n; i++) { if (isalpha(buf[i])) { p[m] = i; //保存字符实际位置 s[m++] = toupper(buf[i]); } } for (i = 0; i < m; i++) //枚举回文串的中间位置 { for (j = 0; i - j >= 0 && i + j < m; j++) //回文子串长度为奇数 { if (s[i - j] != s[i + j]) break; if (j * 2 + 1 > max) { max = j * 2 + 1; x = p[i - j]; y = p[i + j]; } } for (j = 0; i - j >= 0 && i + j + 1 < m; j++) //回文串长度为偶数 { if (s[i - j] != s[i + j + 1]) break; if (j * 2 + 2 > max) { max = j * 2 + 2; x = p[i - j]; y = p[i + j + 1]; } } } for (i = x; i <= y; i++) printf("%c", buf[i]); printf("\n"); return 0; }解析:枚举回文串的中间位置时要注意长度为奇数和偶数的处理方式是不一样的。
7题:编码实现求给定字符串(全为小写英文字母)的最小后继,如"abc"的最小后继为"abd","dhz"的最小后继为"di"。(Google笔试题)
#include <stdio.h> #include <string.h> #define MAXN 1024 int main(void) { char buf[MAXN]; int n, m, i; scanf("%s", buf); n = strlen(buf); for (i = n - 1; i >= 0; i--) { if (buf[i] + 1 <= 'z') { buf[i] += 1; buf[i + 1] = '\0'; break; } } printf("%s\n", buf); return 0; }
解析:对最后一个字符+1,假设大于'z'则对前一个字符+1,假设又大于 'z' 则反复之前的步骤。
8题:X86结构下,以下代码的printf输出结果是什么?(西艾面试题)
#include <stdio.h> int main(void) { char str[20]="Good night"; int *p = (int *)str; p[0] = 0x61626364; p[1] = 0x31323334; p[2] = 0x41424344; printf("%s\n", str); return 0; }
解析:输出结果为:dcba4321DCBA。X86结构下,数据的低位保存在内存的低地址中,数据的高位保存在内存的高地址中。还须要注意常见字符的ASCII码(十进制),’a’为97,’A’为65,’1’为49。
9题:编一个函数,输入一个字符串,要求做一个新字符串,把当中全部的一个或多个连续的空白字符都压缩为一个空格。这里所说的空白包含空格、'\t'、'\n'、'\r'。比如原来的字符串是:
This Content hoho is ok
ok?
file system
uttered words ok ok ?
end.
压缩了空白之后就是:
This Content hoho is ok ok? file systemuttered words ok ok ? end.(面试题)
參考程序例如以下:#include <stdio.h> #include <string.h> #include <stdlib.h> const char *p = "This Content hoho is ok\ ok?\ \ file system\n\ uttered words ok ok ?\ end."; int IsSpace(char c) { if (c == ' ') return 1; else if (c == '\n' || c == '\r') return 2; else if (c == '\t') return 3; else return 0; } char *shrink_space(char *dest, const char *src, size_t n) { char *t_dest = dest; char temp; int pre = -1, cur = -1, key = -1; while (IsSpace(*src)) //忽略字符串起始空格 src++; *t_dest = *src; while ((temp = *src++) != '\0') { key = IsSpace(temp); if (0 == key) //0表示字符 { cur = 0; *t_dest++ = temp; } else if (1 == key) //1表示空格 { if (pre == 1) //假设前面也是空格 continue; else { cur = 1; *t_dest++ = temp; } } else if (2 == key && pre == 0) { *t_dest++ = ' '; } else if (3 == key) { if (pre == 1) continue; else { *t_dest++ = ' '; //将\t转换为1个空格 cur = 1; } } pre = cur; } *t_dest = '\0'; return dest; } int main(void) { int len = strlen(p); char *dest = (char *)malloc(sizeof(char) * (len + 1)); shrink_space(dest, p, 1); printf("%s\n", dest); free(dest); dest = NULL; return 0; }
10题:写出在母串中查找子串出现次数的代码。(面试题)
#include <stdio.h> #include <string.h> #define BUFSIZE 1024 int StrCount(char *strLong, char *strShort) { int result = 0; char *t_strS = strShort; char *t_strD = strLong; while (*t_strD != '\0') { t_strS = strShort; //子串 while (*t_strD == *t_strS && *t_strS != '\0' && *t_strD != '\0') { t_strD++; t_strS++; } if (*t_strS == '\0') result += 1; else if (*t_strD == '\0') break; else t_strD++; } return result; } int main(void) { int len; char strD[BUFSIZE], strS[BUFSIZE]; fgets(strD, sizeof(strD), stdin); len = strlen(strD); strD[len - 1] = '\0'; fgets(strS, sizeof(strS), stdin); len = strlen(strS); strS[len - 1] = '\0'; printf("%d\n", StrCount(strD, strS)); return 0; }