目录
string类__知识总结
1、定义
比如
string str="";//ATTENTION: 不可''
string str("");//ATTENTION: 不可''
可以像 C 语言中一样,将 string 对象当做一个数组,然后使用数组下标的方式来访问字符串中的元素;也可以使用 string.at(index) 的方式来访问元素(索引号从 0 开始):
cout << str[1] << endl; // 使用数组下标的方式访问 string 字符串的元素 cout << str.at(1) << endl; // 使用 at 索引访问 string 字符串的元素
(1)长度:在 C++ 中,可以使用 string.size() 函数或 string.length() 函数来获得 string 对象的长度
(2)复制:在 C 语言中,使用 strcpy、strncpy 函数来实现字符串的复制。在 C++ 中则方便很多,可以直接将一个 string 对象赋值给另一个 string 对象:str2 = str1;
(3)拼接:在 C 语言中,使用 strcat、strncat 函数来进行字符串拼接操作。在 C++ 中也有多种方法来实现字符串拼接和附加操作:
方法1:string str3 = str1 + str2;
方法2:str1.append(str2);
方法3:str.push_back('a');//只能是一个字符
(4)比较:在 C 语言中,使用 strcmp、strncmp 函数来进行字符串的比较。在 C++ 中,由于将 string 对象声明为了简单变量,故而对字符串的比较操作十分简单了,直接使用关系运算符(==、!=、<、<=、>、>=)即可。或者 string.compare() 方法。
(5)子字符串 使用 str = string.substr(起始位置,子字符串长度) 函数来获取子串
(6)查找string.find()
//从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找子字符串 str。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos:
size_type find (const string& str, size_type pos = 0) const;
//从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找子字符串 s。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos:
size_type find (const char *s, size_type pos = 0) const;
//从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找 s 的前 n 个字符组成的子字符串。如果找到,则返回该子字符串首次出现时其首字符的索引;否则,返回 string::npos:
size_type find (const char *s, size_type pos, size_type n);
//从字符串的 pos 位置开始(若不指定 pos 的值,则默认从索引 0 处开始),查找字符 ch 。如果找到,则返回该字符首次出现的位置;否则,返回 string::npos:
size_type find (char ch, size_type pos = 0) const;
(7)插入string.insert()
// 在位置 pos 处插入字符串 str
string&insert(size_t pos,const string&str);
// 在位置 pos 处插入字符串 str 的从位置 subpos 处开始的 sublen 个字符
string&insert(size_t pos,const string&str,size_t subpos,size_t sublen);
// 在位置 pos 处插入字符串 s
string&insert(size_t pos,const char * s);
// 在位置 pos 处插入字符串 s 的前 n 个字符
string&insert(size_t pos,const char * s,size_t n);
// 在位置 pos 处插入 n 个字符 c
string&insert(size_t pos,size_t n,char c);
// 在 p 处插入 n 个字符 c,并返回插入后迭代器的位置
iterator insert (const_iterator p, size_t n, char c);
// 在 p 处插入字符 c,并返回插入后迭代器的位置
iterator insert (const_iterator p, char c);
(8)删除string.erase
// 删除从 pos 处开始的 n 个字符
string& erase (size_t pos = 0, size_t len = npos);
// 删除 p 处的一个字符,并返回删除后迭代器的位置
iterator erase (const_iterator p);
// 删除从 first 到 last 之间的字符,并返回删除后迭代器的位置
iterator erase (const_iterator first, const_iterator last);
(9)交换:str1.swap(str2);
(10)判断是否为空:str.empty();
(11)反转:reverse (res.begin(), res.end());
344.反转字符串
建议: 本题是字符串基础题目,就是考察 reverse 函数的实现,同时也明确一下 平时刷题什么时候用 库函数,什么时候 不用库函数。
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
文章讲解/视频讲解:代码随想录
class Solution {
public:
void reverseString(vector<char>& s) {
for(int i = 0; i < s.size()/2; i++){
swap(s[i],s[s.size()-1-i]);
}
}
};
541. 反转字符串II
建议:本题又进阶了,自己先去独立做一做,然后在看题解,对代码技巧会有很深的体会。
题目链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台
文章讲解/视频讲解:代码随想录
class Solution {
public:
string reverseStr(string s, int k) {
for(int i = 0; i < s.size(); i = i + 2 * k){
if(i+k<s.size()){//如果剩余字符小于 2k 但大于或等于 k 个
reverse(s.begin()+i, s.begin()+i+k);//则反转前 k 个字符,其余字符保持原样
}else{//如果剩余字符少于 k 个
reverse(s.begin()+i, s.end());//则将剩余字符全部反转
}
}
return s;
}
};
卡码网:54.替换数字
建议:对于线性数据结构,填充或者删除,后序处理会高效的多。好好体会一下。
题目链接:题目页面
文章讲解:代码随想录
链接字符串不必执着用strcat(s1,s2),直接用+就行了呀!
#include <string>
#include <iostream>
using namespace std;
int main(){
string str;
cin >> str ;
string strOut;
for(char c : str){
if(c >= 'a' && c <='z'){
strOut += c;
}
if(c >='0' && c <= '9'){
strOut += "number";
}
}
cout << strOut << endl;
return 0;
}
#include<iostream>
using namespace std;
int main() {
string s;
while (cin >> s) {//ATTENTION
int count = 0;
for(char c : s){
if(c>='0'&&c<='9'){
count ++;
}
}
int soldsize = s.size();
s.resize(s.size() + count * 5);
int snewsize = s.size();
for(int fast = soldsize-1, slow = snewsize-1; fast < slow;fast--,slow--){
if(s[fast]>='0'&&s[fast]<='9'){
s[slow]='r';
s[slow-1]='e';
s[slow-2]='b';
s[slow-3]='m';
s[slow-4]='u';
s[slow-5]='n';
slow = slow - 5;
}else{
s[slow]=s[fast];
}
}
std::cout << s << std::endl;
}
}
上面这种做法不用申请新的字符串数组。很多数组填充类的问题,其做法都是先预先给数组扩容带填充后的大小,然后在从后向前进行操作
151.反转字符串里的单词 【有难度待补充】
建议:这道题目基本把 刚刚做过的字符串操作 都覆盖了,不过就算知道解题思路,本题代码并不容易写,要多练一练。
题目链接:151. 反转字符串中的单词 - 力扣(LeetCode)
文章讲解/视频讲解:代码随想录
有一种运用stringstream的方法
class Solution {
public:
string reverseWords(string s) {
stringstream ss(s);
string cur;
string ans;
bool isFirst = true;
while(ss >> cur){
if(isFirst == true){
ans += cur;
isFirst = false;
}else{
ans = cur +' '+ ans;
}
}
return ans;
}
};
满射问题/判断是否具有相同规律【hush表】
class Solution {
public:
bool isIsomorphic(string s, string t) {
if(s.size() != t.size()){
return false;
}
unordered_map<char,char> maps2t;
unordered_map<char,char> mapt2s;
int n = s.size();
for(int i = 0; i < n; i ++){
if(maps2t.find(s[i]) == maps2t.end()){
maps2t[s[i]] = t[i];
}
if(mapt2s.find(t[i]) == mapt2s.end()){
mapt2s[t[i]] = s[i];
}
if(maps2t.find(s[i]) != maps2t.end() && maps2t[s[i]] != t[i] ||
mapt2s.find(t[i]) != mapt2s.end() && mapt2s[t[i]] != s[i]){
return false;
}
}
return true;
}
};
class Solution {
public:
bool wordPattern(string pattern, string s) {
unordered_map<char,string> maps2t;
unordered_map<string,char> mapt2s;
vector<string> vec = st2vec(s);
if(pattern.size() != vec.size()) return false;
int n = vec.size();
for(int i = 0; i < n; i ++){
if(maps2t.find(pattern[i]) == maps2t.end()){
maps2t[pattern[i]] = vec[i];
}
if(mapt2s.find(vec[i]) == mapt2s.end()){
mapt2s[vec[i]] = pattern[i];
}
if(maps2t.find(pattern[i]) != maps2t.end() && maps2t[pattern[i]] != vec[i] ||
mapt2s.find(vec[i]) != mapt2s.end() && mapt2s[vec[i]] != pattern[i]){
return false;
}
}
return true;
}
private:
vector<string> st2vec(string str){
vector<string> res;
string word = "";
for(char i : str){
if(i == ' '){
res.push_back(word);
word= "";
}else{
word += i;
}
}
res.push_back(word);
return res;
}
};
55.右旋转字符串-卡码网
建议:题解中的解法如果没接触过的话,应该会想不到;第二遍看还是没想到。
题目链接:题目页面 (kamacoder.com)
文章讲解:代码随想录
#include<iostream>
#include<algorithm>
using namespace std;
int main(){
int n ;
string s ;
string s1;
string s2;
cin >> n ;
cin >> s ;
// s1 = s[0 : s.size()-n];
// s2 = s[s.size()-n : -1];
// cout << s2 + s1 <<endl;
reverse(s.begin(), s.end()); // 整体反转
reverse(s.begin(), s.begin() + n); // 先反转前一段,长度n
reverse(s.begin() + n, s.end()); // 再反转后一段
cout << s <<endl;
}
28. KMP - 实现 strStr() 【待补充】
因为KMP算法很难,大家别奢求 一次就把kmp全理解了,大家刚学KMP一定会有各种各样的疑问,先留着,别期望立刻啃明白,第一遍了解大概思路,二刷的时候,再看KMP会 好懂很多。
或者说大家可以放弃一刷可以不看KMP,今天来回顾一下之前的算法题目就可以。
因为大家 算法能力还没到,细扣 很难的算法,会把自己绕进去,就算别人给解释,只会激发出更多的问题和疑惑。所以大家先了解大体过程,知道这么回事, 等自己有 算法基础和思维了,在看多看几遍视频,慢慢就理解了。
题目链接:
文章讲解/视频讲解:代码随想录
459. KMP 重复的子字符串 【待补充】
本题算是KMP算法的一个应用,不过 对KMP了解不够熟练的话,理解本题就难很多。
我的建议是 KMP和本题,一刷的时候 ,可以适当放过,了解怎么回事就行,二刷的时候再来硬啃
题目链接:
文章讲解/视频讲解:代码随想录
用的KMP
暴力解法的话
class Solution {
public:
int strStr(string haystack, string needle) {
int i, j;
for(i = 0; i < haystack.size(); i++){
for(j = 0; j < needle.size(); j++){
if(haystack[i + j] != needle[j]) break;
}
if (j == needle.size()) return i;
}
return -1;
}
};
字符串总结
题目链接/文章讲解:代码随想录
双指针回顾
文章讲解:代码随想录