题意:
题目意思简化:
给出n个只包含小写字母'a'~'z'的字符串,如果存在一个其他串某个串的前缀,则舍弃掉,问剩余串的数量?


方法一:
直接模拟

思路:二重循环模拟,vis[i]初始值都为0,表示都未被舍弃。
如果s[i]是s[j]的前缀,则舍弃掉s[j],将vis[j]赋值为1。
class Solution {
public:
    
    int solve(int n, vector<string>& s) {
        int num=n;//num设为总数n
        vector<int> vis(n,0);
        for(int i=0;i<n;i++){
            if(vis[i])//该字符串已被舍弃,跳过
                continue;
            for(int j=0;j<n;j++){
                if(i==j)//跳过自己与自己比较
                    continue;
                if(s[i]==s[j].substr(0,s[i].size())){//如果s[i]是s[j]的前缀,则舍弃掉s[j],将vis[j]赋值为1
                    vis[j]=1;
                    num--;//数量减一
                }
            }
        }
        return num;
    }
};

时间复杂度:
空间复杂度:

方法二:
字典树

思路:

先将所有字符串插入,构造树。
再遍历每个字符串,到构建的树中查找。
如果存在相同字符串或前缀,则舍弃该字符串。
表示某字符串在树中的数量。

class Solution {
    
public:
    int son[1000005][26],tail[1000005];
    int id=0;//节点编号
    int num=0;
    
    void insert(string str){//插入字符串
        
        int now=0;//根节点编号为0
        int num=str.size();
        for(int i=0;i<num;i++){//遍历每个字符
            int x=str[i]-'a';
            if(son[now][x]==0)//如果不存在节点,则新建节点
                son[now][x]=++id;
            now=son[now][x];//递归下去
        }
        tail[now]++;//该字符串在树中的数量加一
    }
    int query(string str){//判断str是否舍弃
        int now=0;//根节点编号为0
        int num=str.size();
        for(int i=0;i<num;i++){
         
            int x=str[i]-'a';
            now=son[now][x];
            //如果存在相同字符串或前缀,则舍弃该字符串
            if((i==num-1&&tail[now]>1)||(i<num-1&&tail[now])){
                return 1;
            }
        }
        return 0;
    }
    
    int solve(int n, vector<string>& s) {
        for(int i=0;i<n;i++){
            insert(s[i]);
        }
        int num=0;//舍弃的数量
        for(int i=0;i<n;i++){
            num+=query(s[i]);
        }
        return n-num;//总的数量-舍弃数量=剩余数量
    }
};

时间复杂度:
空间复杂度: