To some string S, we will perform some replacement operations that replace groups of letters with new ones (not necessarily the same size).

Each replacement operation has 3 parameters: a starting index i, a source word x and a target word y.  The rule is that if x starts at position i in the original string S, then we will replace that occurrence of x with y.  If not, we do nothing.

For example, if we have S = "abcd" and we have some replacement operation i = 2, x = "cd", y = "ffff", then because "cd" starts at position 2 in the original string S, we will replace it with "ffff".

Using another example on S = "abcd", if we have both the replacement operation i = 0, x = "ab", y = "eee", as well as another replacement operation i = 2, x = "ec", y = "ffff", this second operation does nothing because in the original string S[2] = 'c', which doesn't match x[0] = 'e'.

All these operations occur simultaneously.  It's guaranteed that there won't be any overlap in replacement: for example, S = "abc", indexes = [0, 1], sources = ["ab","bc"] is not a valid test case.

Example 1:

Input: S = "abcd", indexes = [0,2], sources = ["a","cd"], targets = ["eee","ffff"]
Output: "eeebffff"
Explanation: "a" starts at index 0 in S, so it's replaced by "eee".
"cd" starts at index 2 in S, so it's replaced by "ffff".

Example 2:

Input: S = "abcd", indexes = [0,2], sources = ["ab","ec"], targets = ["eee","ffff"]
Output: "eeecd"
Explanation: "ab" starts at index 0 in S, so it's replaced by "eee".
"ec" doesn't starts at index 2 in the original S, so we do nothing.

Notes:

  1. 0 <= indexes.length = sources.length = targets.length <= 100
  2. 0 < indexes[i] < S.length <= 1000
  3. All characters in given inputs are lowercase letters.

这道题给了我们一个字符串S,并给了一个坐标数组,还有一个源字符串数组,还有目标字符串数组,意思是若某个坐标位置起,源字符串数组中对应位置的字符串出现了,将其替换为目标字符串。题目真的是好长,但好在给了两个例子可以帮助我们很好的理解题意。此题的核心操作就两个,查找和替换,需要注意的是,由于替换操作会改变原字符串,但是我们查找始终是基于最初始的S,比如例子2中,当完成了第一次替换后,S变为了 "eeecd",好像此时 "ec" 出现了,但仍然不能替换,因为一切查找都是基于最原始的那个S。那么正向的替换可能会产生这样的问题,我们注意到题目中有个限制条件,就是说不会有重叠产生,比如 "abc",如果让在0位置上查找 "ab" 了,就不会让在1位置上查找 "bc",这样的话,其实我们可以从后往前开始查找替换,因为不会有重叠,所以后面替换了的字符不会影响到前面。首先我们需要给indexes数组排个序,因为可能不是有序的,但是却不能直接排序,这样会丢失和sources,targets数组的对应关系,这很麻烦。所以我们新建了一个保存pair对儿的数组,将indexes数组中的数字跟其位置坐标组成pair对儿,加入新数组v中,然后给这个新数组按从大到小的方式排序,这样我们既排了序,又保存了对应关系,岂不美哉!

下面就要开始遍历新数组v了,对于遍历到的pair对儿,取出第一个数字,保存到i,表示S中需要查找的位置,取出第二个数字,然后根据这个位置分别到sources和targets数组中取出源字符串和目标字符串,然后我们在S中的i位置,向后取出和源字符串长度相同的子串,然后比较,若正好和源字符串相等,则将其替换为目标字符串即可,参见代码如下:

解法一:

class Solution {
public:
string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) {
vector<pair<int, int>> v;
for (int i = ; i < indexes.size(); ++i) {
v.push_back({indexes[i], i});
}
sort(v.rbegin(), v.rend());
for (auto a : v) {
int i = a.first;
string s = sources[a.second], t = targets[a.second];
if (S.substr(i, s.size()) == s) {
S = S.substr(, i) + t + S.substr(i + s.size());
}
}
return S;
}
};

我们也可以使用TreeMap来代替需要排序的数组,由于TreeMap默认的是最小堆,而我们需要的是最大堆,只要在定义上加一个greater就行了,其他部分基本没有任何的区别,参见代码如下:

解法二:

class Solution {
public:
string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) {
map<int, int, greater<int>> m;
for (int i = ; i < indexes.size(); ++i) {
m[indexes[i]] = i;
}
for (auto a : m) {
int i = a.first;
string s = sources[a.second], t = targets[a.second];
if (S.substr(i, s.size()) == s) {
S = S.substr(, i) + t + S.substr(i + s.size());
}
}
return S;
}
};

再来看一种稍有不同的解法,之前的两种解法都是直接在S上替换,这里我们新建一个结果res字符串,这里还是使用HashMap来保存映射对,但是稍有不同的是,我们并不是无脑的添加所有的映射对儿,而是先做个check,只要当发现可以查找到源字符串位置的时候,才添加映射对儿,这样就排除了所有不能替换的情况。然后我们遍历原字符串S,对于每个遍历到的位置,我们都到HashMap中查找,如果发现需要替换,我们就把目标字符串提取出来,加入结果res中,注意此时i也需要加上源字符串的长度。若不需要替换,则直接将字符加入结果res中,然后i移动到下一个位置,参见代码如下:

解法三:

class Solution {
public:
string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) {
string res = "";
unordered_map<int, int> m;
for (int i = ; i < indexes.size(); ++i) {
if (S.substr(indexes[i], sources[i].size()) == sources[i]) {
m[indexes[i]] = i;
}
}
for (int i = ; i < S.size();) {
if (m.count(i)) {
res += targets[m[i]];
i += sources[m[i]].size();
} else {
res.push_back(S[i]);
++i;
}
}
return res;
}
};

我们也可以使用STL自带的replace函数来完成替换操作,有点偷懒啊~

解法四:

class Solution {
public:
string findReplaceString(string S, vector<int>& indexes, vector<string>& sources, vector<string>& targets) {
map<int, pair<int, string>, greater<int>> m;
for (int i = ; i < indexes.size(); ++i) {
if (S.substr(indexes[i], sources[i].size()) == sources[i]) {
m[indexes[i]] = {sources[i].size(), targets[i]};
}
}
for (auto a : m) {
S.replace(a.first, a.second.first, a.second.second);
}
return S;
}
};

参考资料:

https://leetcode.com/problems/find-and-replace-in-string/

https://leetcode.com/problems/find-and-replace-in-string/discuss/134758/Java-O(n)-solution

https://leetcode.com/problems/find-and-replace-in-string/discuss/130577/C%2B%2B-5-lines-6-ms-bucket-sort-O(n)

https://leetcode.com/problems/find-and-replace-in-string/discuss/130587/C%2B%2BJavaPython-Replace-S-from-right-to-left

LeetCode All in One 题目讲解汇总(持续更新中...)

[LeetCode] Find And Replace in String 在字符串中查找和替换的更多相关文章

  1. hiho1482出勤记录II(string类字符串中查找字符串,库函数的应用)

    string类中有很多好用的函数,这里介绍在string类字符串中查找字符串的函数. string类字符串中查找字符串一般可以用: 1.s.find(s1)函数,从前往后查找与目标字符串匹配的第一个位 ...

  2. [LeetCode] Reverse Words in a String 翻转字符串中的单词

    Given an input string, reverse the string word by word. For example, Given s = "the sky is blue ...

  3. [LeetCode] Unique Substrings in Wraparound String 封装字符串中的独特子字符串

    Consider the string s to be the infinite wraparound string of "abcdefghijklmnopqrstuvwxyz" ...

  4. [LeetCode] Reverse Vowels of a String 翻转字符串中的元音字母

    Write a function that takes a string as input and reverse only the vowels of a string. Example 1:Giv ...

  5. leetcode——Reverse Words in a String 旋转字符串中单词顺序(AC)

    题目例如以下: Given an input string, reverse the string word by word. For example, Given s = "the sky ...

  6. 将一个字符串中的空格替换成“%20”(C、Python)

    将一个字符串中的空格替换成“%20” C语言: /* ----------------------------------- 通过函数调用,传地址来操作字符串 1.先计算出替换后的字符串的长度 2.从 ...

  7. 实现字符串的查找和替换 分类: c/c++ 2014-10-09 22:33 469人阅读 评论(0) 收藏

    在字符串中查找目标字符串并将其替换为指定字符串,返回替换的次数.接口为 int find_str_replace(char *&str,const char *find_str,const c ...

  8. 《剑指offer面试题4》替换空格——实现函数把字符串中每个空格替换成“%20”

    思路: 例如把we are happy这个字符串中所有空格替换成"%20",最直接的做法是从头开始扫苗,遇到空格就替换,并且把空格后面的字符都顺序后移.复杂度O(n^2). 重要思 ...

  9. sh_17_字符串的查找和替换

    sh_17_字符串的查找和替换 hello_str = "hello world" # 1. 判断是否以指定字符串开始 print(hello_str.startswith(&qu ...

随机推荐

  1. CSS 实现滚动进度条效果

    参考:https://www.w3cplus.com/css/pure-css-create-scroll-indicator.html 前言:细化总结.参考的文章作者已经写的很详细了.这里在从初学者 ...

  2. mingw-gcc-8.3.0-i686-posix-sjlj

    网上无法找到 gcc-8.3.0 的 posix 版本, 所以自己编译了这个版本 gcc -v Using built-in specs. COLLECT_GCC=d:\msys\mingw\bin\ ...

  3. 【easy】101. Symmetric Tree

    判断一棵二叉树是否对称 /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left ...

  4. C++中public/protect/private三种访问权限控制

    一.成员访问权限控制 1.public (1)public成员变量可以被成员函数访问  [访问性] (2)public成员可以被实体对象访问  [访问性] (3)public成员可以成为子类成员  [ ...

  5. python-基于tcp协议的套接字(加强版)及粘包问题

    一.基于tcp协议的套接字(通信循环+链接循环) 服务端应该遵循: 1.绑定一个固定的ip和port 2.一直对外提供服务,稳定运行 3.能够支持并发 基础版套接字: from socket impo ...

  6. 小米众筹新品---8H凉感慢回弹记忆绵枕 99元 上手开箱图

    在众目睽睽之下,商城终于成了杂货铺 众筹发布了第98期新品——8H凉感慢回弹记忆绵枕H1,售价为99元,主打舒适凉感,抗菌吸湿,三曲线护颈设计,3~5秒慢回弹. 本着程序员的读书历程:x 语言入门 — ...

  7. tomcat 网页管理tomcat

    一.设置管理员账户密码 进入tomcat安装目录 ->进入conf目录->修改user.xml->加入下面内容 模板 <role rolename="manager- ...

  8. cpu-z笔记本加条子

    前天:给笔记本升级能升级的东西就两个,一个内存条,一个光驱换固态硬盘,我说下升级内存 1.先将自己笔记本的型号上中关村在线查下自己的笔记本型号最大能支持多大的内存扩容 中关村在线网站:http://n ...

  9. python3与mysql交互

    1.安装pymysql模块 pip3 install pymysql3 2.pymysql的简单使用: # /usr/bin/env python3 import pymysql class Mysq ...

  10. OpenCV中的KNN

    一.K近邻 有两个类,红色.蓝色.我将红色点标记为0,蓝色点标记为1.还要创建25个训练数据,把它们分别标记为0或者1.Numpy中随机数产生器可以帮助我们完成这个任务 import cv2 impo ...