字符串类习题、面试题详解(第二篇)
第一篇链接:字符串类习题、面试题详解(第一篇)
6题:回文串(竞赛基础题)
输入一个字符串,求出其最长回文子串。子串的含义是:在原串中连续出现的字符串片段。回文的含义是:正着看和倒着看相同,如abba和yyxyy。在判断时,应该忽略所有标点符号和空格,且忽略大小写,但输出应保持原样(在回文串的首部和尾部不要输出多余字符)。输入字符串长度不超过5000,且占据单独一行。应该输出最长的回文串,如果有多个,输出起始位置最靠左的。
样例输入:Confuciuss say: Madam, I’m Adam.
样例输出:Madam,I’m Adam
方法1:枚举回文串的起点和终点。
1 #include <stdio.h> 2 #include <ctype.h> 3 #include <string.h> 4 #define MAXN 5000 + 10 5 6 char buf[MAXN], s[MAXN]; 7 int p[MAXN]; 8 9 int main(void) 10 { 11 int n, m = 0, max = 0, x = 0, y = 0; 12 int i, j, k, ok; 13 fgets(buf, sizeof(buf), stdin); 14 n = strlen(buf); 15 16 for (i = 0; i < n; i++) 17 { 18 if (isalpha(buf[i])) 19 { 20 p[m] = i; //保存字符的实际位置 21 s[m++] = toupper(buf[i]); //保存为大写字母 22 } 23 } 24 25 for (i = 0; i < m; i++) //枚举回文串起始位置 26 { 27 for (j = i; j < m; j++) //枚举回文串终止位置 28 { 29 ok = 1; 30 for (k = i; k <= j; k++) 31 { 32 if (s[k] != s[i + j - k]) 33 ok = 0; 34 } 35 36 if (ok && j - i + 1 > max) 37 { 38 max = j - i + 1; 39 x = p[i]; 40 y = p[j]; 41 } 42 } 43 } 44 45 for (i = x; i <= y; i++) 46 { 47 printf("%c", buf[i]); 48 } 49 printf("\n"); 50 51 return 0; 52 }
方法2:枚举回文串的中间位置。
1 #include <stdio.h> 2 #include <string.h> 3 #include <ctype.h> 4 #define MAXN 5000 + 10 5 char buf[MAXN], s[MAXN]; 6 int p[MAXN]; 7 8 int main(void) 9 { 10 int n, m = 0, max = 0, x = 0, y = 0; 11 int i, j; 12 fgets(buf, sizeof(buf), stdin); 13 n = strlen(buf); 14 15 for (i = 0; i < n; i++) 16 { 17 if (isalpha(buf[i])) 18 { 19 p[m] = i; //保存字符实际位置 20 s[m++] = toupper(buf[i]); 21 } 22 } 23 24 for (i = 0; i < m; i++) //枚举回文串的中间位置 25 { 26 for (j = 0; i - j >= 0 && i + j < m; j++) //回文子串长度为奇数 27 { 28 if (s[i - j] != s[i + j]) 29 break; 30 if (j * 2 + 1 > max) 31 { 32 max = j * 2 + 1; 33 x = p[i - j]; 34 y = p[i + j]; 35 } 36 } 37 38 for (j = 0; i - j >= 0 && i + j + 1 < m; j++) //回文串长度为偶数 39 { 40 if (s[i - j] != s[i + j + 1]) 41 break; 42 if (j * 2 + 2 > max) 43 { 44 max = j * 2 + 2; 45 x = p[i - j]; 46 y = p[i + j + 1]; 47 } 48 } 49 } 50 51 for (i = x; i <= y; i++) 52 printf("%c", buf[i]); 53 printf("\n"); 54 55 return 0; 56 }
解析:枚举回文串的中间位置时要注意长度为奇数和偶数的处理方式是不一样的。
7题:编码实现求给定字符串(全为小写英文字母)的最小后继,如"abc"的最小后继为"abd","dhz"的最小后继为"di"。(Google笔试题)
1 #include <stdio.h> 2 #include <string.h> 3 #define MAXN 1024 4 5 int main(void) 6 { 7 char buf[MAXN]; 8 int n, m, i; 9 scanf("%s", buf); 10 11 n = strlen(buf); 12 for (i = n - 1; i >= 0; i--) 13 { 14 if (buf[i] + 1 <= 'z') 15 { 16 buf[i] += 1; 17 buf[i + 1] = '\0'; 18 break; 19 } 20 } 21 printf("%s\n", buf); 22 23 return 0; 24 }
解析:对最后一个字符+1,如果大于'z'则对前一个字符+1,如果又大于 'z' 则重复之前的步骤。
8题:X86结构下,下面代码的printf输出结果是什么?(西艾面试题)
1 #include <stdio.h> 2 3 int main(void) 4 { 5 char str[20]="Good night"; 6 int *p = (int *)str; 7 p[0] = 0x61626364; 8 p[1] = 0x31323334; 9 p[2] = 0x41424344; 10 printf("%s\n", str); 11 12 return 0; 13 }
解析:输出结果为: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.(面试题)
参考程序如下:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 5 const char *p = "This Content hoho is ok\ 6 ok?\ 7 \ 8 file system\n\ 9 uttered words ok ok ?\ 10 end."; 11 12 int IsSpace(char c) 13 { 14 if (c == ' ') 15 return 1; 16 else if (c == '\n' || c == '\r') 17 return 2; 18 else if (c == '\t') 19 return 3; 20 else 21 return 0; 22 } 23 24 char *shrink_space(char *dest, const char *src, size_t n) 25 { 26 char *t_dest = dest; 27 char temp; 28 int pre = -1, cur = -1, key = -1; 29 while (IsSpace(*src)) //忽略字符串起始空格 30 src++; 31 *t_dest = *src; 32 33 while ((temp = *src++) != '\0') 34 { 35 key = IsSpace(temp); 36 if (0 == key) //0表示字符 37 { 38 cur = 0; 39 *t_dest++ = temp; 40 } 41 else if (1 == key) //1表示空格 42 { 43 if (pre == 1) //如果前面也是空格 44 continue; 45 else 46 { 47 cur = 1; 48 *t_dest++ = temp; 49 } 50 } 51 else if (2 == key && pre == 0) 52 { 53 *t_dest++ = ' '; 54 } 55 else if (3 == key) 56 { 57 if (pre == 1) 58 continue; 59 else 60 { 61 *t_dest++ = ' '; //将\t转换为1个空格 62 cur = 1; 63 } 64 } 65 pre = cur; 66 } 67 *t_dest = '\0'; 68 69 return dest; 70 } 71 int main(void) 72 { 73 int len = strlen(p); 74 char *dest = (char *)malloc(sizeof(char) * (len + 1)); 75 shrink_space(dest, p, 1); 76 printf("%s\n", dest); 77 free(dest); 78 dest = NULL; 79 80 return 0; 81 }
10题:写出在母串中查找子串出现次数的代码。(面试题)
1 #include <stdio.h> 2 #include <string.h> 3 #define BUFSIZE 1024 4 5 int StrCount(char *strLong, char *strShort) 6 { 7 int result = 0; 8 char *t_strS = strShort; 9 char *t_strD = strLong; 10 while (*t_strD != '\0') 11 { 12 t_strS = strShort; //子串 13 while (*t_strD == *t_strS && *t_strS != '\0' && *t_strD != '\0') 14 { 15 t_strD++; 16 t_strS++; 17 } 18 if (*t_strS == '\0') 19 result += 1; 20 else if (*t_strD == '\0') 21 break; 22 else 23 t_strD++; 24 } 25 26 return result; 27 } 28 29 int main(void) 30 { 31 int len; 32 char strD[BUFSIZE], strS[BUFSIZE]; 33 fgets(strD, sizeof(strD), stdin); 34 len = strlen(strD); 35 strD[len - 1] = '\0'; 36 fgets(strS, sizeof(strS), stdin); 37 len = strlen(strS); 38 strS[len - 1] = '\0'; 39 printf("%d\n", StrCount(strD, strS)); 40 return 0; 41 }