思路:

题目的主要信息:

  • 字符串t与字符串s的前缀(从头开始,取前t.length个),若是二者所有的奇数位字符串都相等则称之为单匹配,若是二者所有偶数位字符串都相等,则称之为双匹配
  • 奇数偶数下标从1开始,注意与字符串下标之间的关系
  • 需要求m个t字符串,各自在n个s字符串中有多少属于单匹配但不属于双匹配,前者是一个完全匹配,后者是一个不完全不匹配(注:不是完全不匹配)
  • 输入只有小写字母

方法一:暴力法
具体做法:
遍历t数组,枚举每一个s进行比较。
每次比较的时候先判断是否是单匹配串,如果是再检查是否是双匹配串,如果不是再把相应的结果加1。
需要注意的是t只有一个字符的情况,双匹配匹配不到,会算作是双匹配而无法计算,需要单独讨论。

class Solution {
public:
    vector<int> solve(int n, vector<string>& s, int m, vector<string>& t) {
        vector<int> res(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只有一个数时
                            res[i]++;
                    }
                }
            }
        }
        return res;
    }
};

复杂度分析:

  • 时间复杂度:表示每个字符串t的长度,外面两层遍历,内部是遍历每个字符串t
  • 空间复杂度:,常数个空间

方法二:字典树
具体做法:
因为我们要找的是完全奇数位匹配且不完全偶数位不匹配,即奇数位必须完全相同,偶数位至少有一位不同。因此我们可以考虑用单匹配的数量减去奇偶完全匹配的数量。
依照这个原理,我们建立两棵字典树:对所有的奇数位置组成的串建立一颗字典树,再对所有完整的建立字典树,同时在字典树上插入的时候顺便记录每个前缀出现次数。后续我们只需要遍历每个字符串,在第一个字典树上查询,再在第二个字典树上查询,单数匹配个数-全匹配个数就是所求答案。
图片说明
和方法一类似,要注意t字符串只有1位的情况。

class Solution {
public:
    vector<int> solve(int n, vector<string>& s, int m, vector<string>& t) {
        vector<int> res(m, 0); //返回答案
        vector<vector<int> > dir(500000, vector<int>(26, 0)); //字典树
        vector<int> sz(500000, 0); //统计前缀出现次数
        int count = 0; //计数
        int r1 = ++count, r2 = ++count;
        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] = ++count;
                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]){
                    count++;
                    dir[p][x] = count;
                }
                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位
                res[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)
                res[i] = temp;
            else
                res[i] = temp - sz[p];
        }
        return res;
    }
};

复杂度分析:

  • 时间复杂度:,建树相当于遍历每个s字符串的每个字符,查询相当于遍历每个t字符串的每个字符
  • 空间复杂度:,字典树最大可达到这个程度