字符串操作

字符串的基本操作对象通常是字符串整体或者其子串,很多时候我们希望对子串进行操作,这是字符串与数组不同的地方之一。且字符串部分操作比数组更加复杂,如比较和连接操作。在c++中,字符串可以用==来实现比较,也可以直接进行连接操作,但是在其他语言如java中不可以直接实现且字符串不可变。

1.查找字符串最长公共前缀

编写一个函数来查找字符串数组中的最长公共前缀。如果不存在公共前缀,返回空字符串 ""

输入:strs = ["flower","flow","flight"]
输出:"fl"

输入:strs = ["dog","racecar","car"]
输出:""

思路:由于寻找公共前缀,不妨设置第一个为公共前缀,然后将其与之后的进行比较,删去不同的部分。

这里使用了c++函数erase(),有三种用法

(1)erase(pos,n); 删除从pos开始的n个字符,例如erase(0,1),删除0位置的一个字符,即删除第一个字符

(2)erase(position); 删除position处的一个字符(position是个string类型的迭代器)

(3)erase(first,last);删除从first到last之间的字符,(first和last都是迭代器)

复制代码
 1 class Solution {
 2 public:
 3     string longestCommonPrefix(vector<string>& strs) {
 4         string same = strs[0];
 5         for(int i =1;i<strs.size();i++){
 6             for(int j=0;j<same.size();j++){
 7                 if(same[j] != strs[i][j]) same.erase(j);
 8             }
 9         }
10         return same;   
11     }
12 };
复制代码

 

2.最长回文字符串: 力扣官方解法

(1)动态规划:

所以我们要找的最长回文字符串就是满足P(i,j)=true的长度j-i+1最大的部分。

注意:在状态转移方程中,我们是从长度较短的字符串向长度较长的字符串进行转移的,因此一定要注意动态规划的循环顺序。

 

复制代码
 1 #include <iostream>
 2 #include <string>
 3 #include <vector>
 4 
 5 using namespace std;
 6 
 7 class Solution {
 8 public:
 9     string longestPalindrome(string s) {
10         int n = s.size();
11         if (n < 2) {
12             return s;
13         }
14 
15         int maxLen = 1;
16         int begin = 0;
17         // dp[i][j] 表示 s[i..j] 是否是回文串
18         vector<vector<int>> dp(n, vector<int>(n));
19         // 初始化:所有长度为 1 的子串都是回文串
20         for (int i = 0; i < n; i++) {
21             dp[i][i] = true;
22         }
23         // 递推开始
24         // 先枚举子串长度
25         for (int L = 2; L <= n; L++) {
26             // 枚举左边界,左边界的上限设置可以宽松一些
27             for (int i = 0; i < n; i++) {
28                 // 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得
29                 int j = L + i - 1;
30                 // 如果右边界越界,就可以退出当前循环
31                 if (j >= n) {
32                     break;
33                 }
34 
35                 if (s[i] != s[j]) {
36                     dp[i][j] = false;
37                 } else {
38                     if (j - i < 3) {
39                         dp[i][j] = true;
40                     } else {
41                         dp[i][j] = dp[i + 1][j - 1];
42                     }
43                 }
44 
45                 // 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置
46                 if (dp[i][j] && j - i + 1 > maxLen) {
47                     maxLen = j - i + 1;
48                     begin = i;
49                 }
50             }
51         }
52         return s.substr(begin, maxLen);
53     }
54 };
复制代码

最后部分使用到字符串截取函数substr(),有两种用法

格式1: substr(string string, int a, int b);  

格式2:substr(string string, int a) ;

格式1:
1、string 需要截取的字符串
2、a 截取字符串的开始位置(注:当a等于0或1时,都是从第一位开始截取)
3、b 要截取的字符串的长度

格式2:
1、string 需要截取的字符串
2、a 可以理解为从第a个字符开始截取后面所有的字符串。

(2)中心扩展:

 

可以看出,这里的边界情况,其实就是回文字符串的中心位置。我们枚举所有的「回文中心」并尝试「扩展」,直到无法扩展为止,此时的回文串长度即为此「回文中心」下的最长回文串长度。我们对所有的长度求出最大值,即可得到最终的答案。

复制代码
 1 class Solution {
 2 public:
 3     pair<int, int> expandAroundCenter(const string& s, int left, int right) {
 4         while (left >= 0 && right < s.size() && s[left] == s[right]) {
 5             --left;
 6             ++right;
 7         }
 8         return {left + 1, right - 1};
 9     }
10 
11     string longestPalindrome(string s) {
12         int start = 0, end = 0;
13         for (int i = 0; i < s.size(); ++i) {
14             auto [left1, right1] = expandAroundCenter(s, i, i);
15             auto [left2, right2] = expandAroundCenter(s, i, i + 1);
16             if (right1 - left1 > end - start) {
17                 start = left1;
18                 end = right1;
19             }
20             if (right2 - left2 > end - start) {
21                 start = left2;
22                 end = right2;
23             }
24         }
25         return s.substr(start, end - start + 1);
26     }
27 };
复制代码

 

3.翻转字符串里的单词:

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

示例 1:

输入:s = "the sky is blue"
输出:"blue is sky the"
示例 2:

输入:s = "  hello world  "
输出:"world hello"
解释:反转后的字符串中不能存在前导空格和尾随空格。
示例 3:

输入:s = "a good   example"
输出:"example good a"
解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。

方法一:自行编写函数

 

posted @   好想学会写代码  阅读(33)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示