String相关操作
1.求字符串中连续出现最多的字串
pair<string, int> substring(const string& str) { int i, j, k, len = str.length(), count, maxcount = 1; string substr; vector<string> substrs; //存储所有的子字符串 for ( i = 0; i < len; ++i) { substrs.push_back(str.substr(i, len - i)); } for ( i = 0; i < len; ++i) { for ( j = i + 1; j < len; ++j) { count = 1; if (substrs[i].substr(0,j-i)==substrs[j].substr(0,j-i)) { ++count; for (k = j + (j - i); k < len; k += j - i) { if (substrs[i].substr(0, j - i) == substrs[k].substr(0, j - i)) { ++count; } else break; } if (count>maxcount) { maxcount = count; substr = substrs[i].substr(0, j - i); } } } } return make_pair(substr, maxcount); }
大致理解,但是有没有更佳的解法呢?
2.求字符串中出现的相同且长度最长的字符串,输出首字符的位置
pair<string, int> substring(const string& str) { string substr{""}; int i, j, left, right, len = str.length(); for (i = len - 1; i > 1; --i) { for ( j = 0; j < len; ++j) { if (j + i < len) { left = right = 0; substr = str.substr(j, i); left = str.find(substr); right = str.rfind(substr); if (left!=right) { return make_pair(substr,left); } } else break; } } return make_pair(substr,0); }
从大字符串进行拆分,两边结合搜索比将所有子字符串拆分寻找效率高。
至于调用库函数,是比较方便的选择。
3.重写strstr,且返回朱传忠字符子串位置以后的所有字符
const char* strstr_(const char* src,const char* substr) { const char* tmp; while (*src!='0') { if (*src==*substr) { tmp = substr; while (*src++==*tmp++) { if (*tmp=='\0') { return src; } } } else *src++; } return nullptr; }
注意其中为什么使用tmp代替字串,因为可能会重复比较,所以需要字串的值持续存在。
3.将字符串中的单词进行倒置,标点符号不倒换。“i come from nanjing!”->"nanjing! from come i".
void transfer(char* dst,const char* src) { bool sign = false; int i, j, k, left, right, num = 0, len = strlen(src); for ( i = 0; i <= len ; i++) { if (' ' != src[i] && '\0' != src[i]) //排除空格 { if (sign) { right++; } else { sign = true; left = right = i; } } else { if (sign) { sign = false; dst[len -1- i] = src[i]; for ( j = left, k = len-1-right; j <= right; j++, k++) { dst[k] = src[j]; } left = right = 0; } else { dst[len-1 - i] = src[i]; } } } }
个人觉得比程序员面试宝典的方法更为简洁,不过其方法较容易操作。后续可以补上程序员面试宝典上的操作。
4.程序员面试宝典上一道填空题,移动字符串内容,将字符串的倒数n个字符移动到字符串前面,仅能在while中填空
void righttransfer(char *str,int n) { int i = 0, len = strlen(str); if (n > len) n = len; while (len - n > 0 || (n = 0) != 0) { for (i = 0, str[len] = str[0], ++n; i < len; i++) str[i] = str[i + 1]; } str[len - n] = '\0'; }
这里面的巧妙之处就在于(n = 0) != 0操作,当字符串移动结束,最后一位'\0'因为移动被字符覆盖了,现在需要重新赋值。
而n已经被修改了,这时候就要重新初始化了,利用||特性,前面为真时直接跳过,此时移动到结尾,len-n为false,则跳到后半部分。
n被赋值为0,即n!=0操作为false,跳出循环,完美。