题意:
题目意思简化:
给出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;//总的数量-舍弃数量=剩余数量
}
};
时间复杂度:
空间复杂度:



京公网安备 11010502036488号