题解 | #单双难全#
单双难全
http://www.nowcoder.com/practice/9e1551271e074f3eb7e9232f6e7846a3
题目描述
有n个只包含小写字母的串s1,s2,..sn,每次给你一个只包含小写字母的串t。如果串S存在前缀S',它的奇数位的字符与t的奇数位字符完全相同,称S为t的单匹配串,如果串S的偶数位字符与t的偶数位的字符全都相同,称S为t的双匹配串。
现在给你m个字符串,对于每个字符串ti,求s1,s2,...sn中有多少个串是t的单匹配串但不是t的双匹配串。
方法一:暴力解法
求解思路
对于本题的求解,我们自然想到可以用暴力循环的方法来解决。我们遍历t数组,枚举每一个s进行比较,每次比较的时候先判断是否是单匹配串,如果是再检查是否是双匹配串。如果是单匹配串不是双匹配串时,我们要把相应的结果加1.因此按照上述思路即可求出本题的答案。
解题代码
class Solution { public: vector<int> solve(int n, vector<string>& s, int m, vector<string>& t) { vector<int> myres(m, 0); for(int i = 0; i < m; i++) { //遍历字符串数组t for(int j = 0; j < n; j++) { //遍历字符串数组s bool flag = true; if(t[i].length() > s[j].length()) continue; else{ for(int k = 0; k < t[i].length(); k++) { //查看是否是单匹配串 if(k % 2 == 0) { //检查奇数是否相同 if(t[i][k] == s[j][k]) continue; else { flag = false; break; } } } if(flag) { //已经是单匹配串 for(int k = 0; k <t[i].length(); k++) { //检查是否是双匹配 if(k % 2 == 1) { if(t[i][k] == s[j][k]) continue; else { flag = false; break; } } } if(!flag || t[i].length() == 1) // 当是单匹配不是双匹配或者t只有一个数时 myres[i]++; // 并且记录结果加1 } } } } return myres; // 返回结果即可 } };
复杂度分析
时间复杂度:两层循环,因此时间复杂度为( )
空间复杂度:没有引入额外的内存地址空间,因此空间复杂度为
方法二:字典树解法--参考云影孤帆尽
求解思路
对于本问题求解,我们即是求奇数位匹配,偶数位至少有一位不同的情况 ,因此我们使用字典树的想法,用单匹配的数量减去奇偶完全匹配的数量,即可得到本问题的答案。
解题代码
class Solution { public: vector<int> solve(int n, vector<string>& s, int m, vector<string>& t) { vector<int> myres(m, 0); // 返回答案 vector<vector<int> > dir(500000, vector<int>(26, 0)); // 字典树 vector<int> sz(500000, 0); // 统计前缀出现次数 int mycount = 0; // 计数 int r1 = ++mycount, r2 = ++mycount; for(int i = 0; i < n; i++) { int p = r1; for(int j = 0; j < s[i].size(); j+=2) { //奇数位的字典树 int x = s[i][j] - 'a'; if(!dir[p][x]) dir[p][x] = ++mycount; sz[p]++; p = dir[p][x]; } sz[p]++; p = r2; for(int j = 0; j < s[i].size(); j++) { //全部位字典树 int x = s[i][j] - 'a'; if(!dir[p][x]) dir[p][x] = ++mycount; sz[p]++; p = dir[p][x]; } sz[p]++; } for(int i = 0; i < m; i++) { //遍历每个t int temp; int p = r1; for(int j = 0; j < t[i].size(); j+=2) { int x = t[i][j] - 'a'; if(!dir[p][x]) { //不是单匹配 p = -1; break; } p = dir[p][x]; } if(p == -1) continue; if(t[i].size() == 1) { //t字符串只有1位 myres[i] = sz[p]; continue; } temp = sz[p]; p = r2; for(int j = 0; j < t[i].size(); j++) { int x = t[i][j] - 'a'; if(!dir[p][x]) { //不是全匹配 p = -1; break; } p = dir[p][x]; } if(p == -1) myres[i] = temp; else myres[i] = temp - sz[p]; } return myres; // 返回结果 } };
复杂度分析
时间复杂度:两层循环,因此时间复杂度为( )
空间复杂度:使用常数级字典树dir[常数][常数],因此空间复杂度为
算法 文章被收录于专栏
算法题的题解以及感受