思路:这题当时陷到统计频率去了,还一直没解决越界的问题,结束后解决越界但超时。统计每个字符串的字母出现频率,按滑动窗口,只比较长度大小差为1的字符串,看是否满足条件。
//超时
class Solution {
public:
bool isok(vector<int>& s, vector<int>& t) {
bool flag = 0;
for(int i = 0; i < 26; i++) {
t[i]--;
if(t == s) {
flag = true;
break;
}
t[i]++;
}
return flag;
}
int wordCount(vector<string>& start, vector<string>& target) {
int n = start.size(), m = target.size();
sort(start.begin(), start.end(), [](const auto& a, const auto& b) {
return a.size() < b.size();
});
sort(target.begin(), target.end(), [](const auto& a, const auto& b) {
return a.size() < b.size();
});
vector<vector<int>> countstart(n, vector<int>(26, 0));
vector<vector<int>> counttarget(m, vector<int>(26, 0));
for(int i = 0; i < n; i++) {
for(auto x : start[i]) {
countstart[i][x-'a']++;
}
}
for(int i = 0; i < m; i++) {
for(auto x : target[i]) {
counttarget[i][x-'a']++;
}
}
int startp = 0;
int ans = 0;
for(int i = 0; i < m; i++){
while(startp < n && start[startp].size() + 1 < target[i].size()) {
startp++;
}
if(startp == n) break;
if(start[startp].size() + 1 > target[i].size()) {
continue;
}
if(start[startp].size() + 1 == target[i].size()) {
for(int j = startp; j < n && start[j].size() + 1 == target[i].size(); j++) {
if(isok(countstart[j], counttarget[i])) {
ans++;
break;
}
}
}
}
return ans;
}
};
可以通过的思路是将所有可以生成的字符串按字母序重排后放入set,对每个target,重排字母序后看在set是否出现。
class Solution {
public:
int wordCount(vector<string>& startWords, vector<string>& targetWords) {
unordered_set<string> hash;
int ans = 0;
for(auto s : startWords) {
string tmp = s;
for(char i = 'a'; i <= 'z'; i++) {
if(tmp.find(i) == tmp.npos) {
tmp += i;
sort(tmp.begin(), tmp.end());
hash.insert(tmp);
tmp = s;
}
}
}
for(auto t : targetWords) {
sort(t.begin(), t.end());
if(hash.find(t) != hash.end()) ans++;
}
return ans;
}
};
另一种更高效的思路,是用二进制表示该位是否有字母出现。
因为题目说明每个字母只出现一次,则每个字符串的状态就是一个长度为26的2进制数组,每一位代表该字母是否出现过,这样用一个int整数就可以表示一个可以生成的字符串,对每个target在set中找它对应整数即可。
这里涉及到位运算,<< 代表左移,即该字母位置对应位置标记为1;|或运算是加上该位的情况;&与运算是看该位是否已有字母,整体思路跟上一方法相同,只是用int表示一个string。
class Solution {
public:
int wordCount(vector<string>& startWords, vector<string>& targetWords) {
unordered_set<int> hash;
int ans = 0;
for(auto s : startWords) {
int tmp = 0;
for(auto c : s) tmp |= (1 << (c - 'a'));
for(int i = 0; i < 26; i++) {
if(!(tmp & (1 << i))) {
hash.insert(tmp | (1 << i));
}
}
}
for(auto t : targetWords) {
int tmp = 0;
for(auto c : t) tmp |= (1 << (c - 'a'));
if(hash.find(tmp) != hash.end()) ans++;
}
return ans;
}
};