1078. Bigram 分词
问题简介
给出第一个词 first 和第二个词 second,考虑在某些文本 text 中可能以 “first second third” 形式出现的情况,其中 second 紧随 first 出现,third 紧随 second 出现。
对于每种这样的情况,将第三个词 “third” 添加到答案中,并返回答案。
示例 1:
输入:text = “alice is a good girl she is a good student”, first = “a”, second = “good”
输出:[“girl”,“student”]
示例 2:
输入:text = “we will we will rock you”, first = “we”, second = “will”
输出:[“we”,“rock”]
提示:
- 1 <= text.length <= 1000
- text 由一些用空格分隔的单词组成,每个单词都由小写英文字母组成
- 1 <= first.length, second.length <= 10
- first 和 second 由小写英文字母组成
解题思路
- 查找第三个单词并确定其位置。
- 将第三个单词从字符串数组中提取出来,放入新的数组。
解决方法
- 因为
first
andsecond
单词是已经确定的,所以可以把二者看成一个字符串,在整个句子中查找。(相当于字符串查找字符串)找到后提取出下一个单词。 - 但是存在一个问题,找到匹配的字符串后,再往后查找不知道在何处截止,所以可以建立一个容器事先存放单词之间空格的位置从而确定单词的位置。
- 找到后通过使用
substr()函数
复制第三个单词,再用push_back()函数压入新建的容器
substr()函数
substr()函数是一种构造string的方法,它的形式是s.substr(pos, n)然后返回一个string,包含s中从pos开始的n个字符的拷贝(pos的默认值是0,n的默认值是s.size() - pos,即不加参数会默认拷贝整个s)
补充:若pos的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则substr会调整n的值,只拷贝到string的末尾
代码
#include<iostream>
#include<string>
#include<vector>
using namespace std;
class Solution {
public:
vector<string> findOcurrences(string text, string first, string second) {
vector<string> res; //存放第三个单词
string tmp = first + ' ' + second; //将第一个单词与第二个单词看成一个整体
int m = tmp.length(); //第一个单词和第二个单词在句子中长度
int n = text.length(); //句子的长度
vector<int> vec; //存放单词位置
for (int i = 0; i < n; i++)
{
if (' ' == text[i])
{
vec.push_back(i);//将空格的位置压入容器
}
}
for (int i = 1; i < vec.size(); i++)
{
if (1 == i)
{
if (text.substr(0, vec[i]) == tmp)
{
if (2 == vec.size())
{
res.push_back(text.substr(vec[i] + 1, n - m - 1));
}
else
{
res.push_back(text.substr(vec[i] + 1, vec[i + 1] - vec[i] - 1));
}
}
}
else
{
if (text.substr(vec[i - 2] + 1, vec[i] - vec[i - 2] - 1) == tmp)
{
if (i == vec.size() - 1)
{
res.push_back(text.substr(vec[i] + 1, n - vec[i]));
}
else
{
res.push_back(text.substr(vec[i] + 1, vec[i + 1] - vec[i] - 1));
}
}
}
}
return res;
}
};
int main() {
Solution s;
string text, first, second;
vector<string> op;
text = "alice is a good girl she is a good student";
first = "a";
second = "good";
op = s.findOcurrences(text, first, second);
for (vector<string>::iterator iter = op.begin(); iter != op.end(); ++iter)
{
//输出*iter才是输出那些字符串
cout << *iter << endl;
}
system("pause");
return 0;
}
代码详解
在查找的情况中有分为三种情况;
- 从开头开始查找
- 在中间开始查找
- 查找到结尾
原因在与存放空格的容器,存储范围是第一二单词之间的位置—倒数第一二单词之间的位置,无法获取字符串的开头与结尾。
-
if (1 == i) vec[i]代表空格的位置,当
i = 1
(即 vec[1]+1表示第三个单词的起始位置)(代表范围开头与中间)-
其中一种是:整个句子只有三个单词,这代表着不存在vec[2]即结尾没有空格压入,所以可以通过两个字符串长度相减获得第三个单词的长度(n-m-1)。第二个和第三个单词之间存在空格。
r e s . p u s h b a c k ( t e x t . s u b s t r ( v e c [ i ] + 1 , n − m − 1 ) ) res.push_back(text.substr(vec[i] + 1, n - m - 1)) res.pushback(text.substr(vec[i]+1,n−m−1))
-
另一种则是字符串的单词数量大于3则
r e s . p u s h b a c k ( t e x t . s u b s t r ( v e c [ i ] + 1 , v e c [ i + 1 ] − v e c [ i ] − 1 ) ) res.push_back(text.substr(vec[i] + 1, vec[i + 1] - vec[i] - 1)) res.pushback(text.substr(vec[i]+1,vec[i+1]−vec[i]−1))
第三个空格的长度减去第二个空格的位置再减去空格本身=第三个单词的长度
-
-
if (1 != i)(代表的范围是结尾与中间)
-
一种是:
i== vec.size() - 1
即查找到结尾r e s . p u s h b a c k ( t e x t . s u b s t r ( v e c [ i ] + 1 , n − v e c [ i ] ) ) res.push_back(text.substr(vec[i] + 1, n - vec[i])) res.pushback(text.substr(vec[i]+1,n−vec[i]))
最大字符串的长度减去vec[i] -
另一种则是字符串单词的查找范围还在中间。
r e s . p u s h b a c k ( t e x t . s u b s t r ( v e c [ i ] + 1 , v e c [ i + 1 ] − v e c [ i ] − 1 ) ) res.push_back(text.substr(vec[i] + 1, vec[i + 1] - vec[i] - 1)) res.pushback(text.substr(vec[i]+1,vec[i+1]−vec[i]−1))
第三个空格的长度减去第二个空格的位置再减去空格本身=第三个单词的长度
-