【任务7】注册与登录:进阶:动态维护敏感词库
上一个任务,大部分人应该是把 敏感词 的维护写死在代码里了,但其实,在正常的线上系统中,肯定是不能写死的,必须得可以动态删除+增加,不然写死的话每次都要更改代码,重新发布系统太麻烦了。
所以呢,我们可以用一个简单的数据库表来动态维护我们的敏感词库,这样你要新增或者删除时,只需要直接操作下数据库就可以了(当然,真实的线上也是不能直接链接数据库写sql的,也是得弄一个可视化界面来弄,不过我们这里就不考虑了)。
所以呢,我们这里维护一个 disallow_word 表,字段有 id, value, type,type 是一个隐藏字段,表示敏感词的类型,但是我们暂时用不到,可以定义为 Int(默认值为0),以后或许会用到,这就是设计表需要关注的点,因为我们得为未来考虑。
之后我们就可以直接从数据库拉敏感词列表来过滤了。
要求:
1、请把你的 敏感词 过滤的算法代码写在下面
2、建表语句也写下面。
本问题对应的项目链接:从0设计一个web项目
PS:每一个打卡,都要给出你的GitHub链接哈,并且代码提交到GitHub
共以下 9 个回答
github仓库:https://github.com/CurryisCoat/community/tree/dev
2.建表语句
CREATE TABLE
disallow_word(idint NOT NULL AUTO_INCREMENT,valuevarchar(255) NOT NULL,typeint NOT NULL DEFAULT ‘0’,PRIMARY KEY (
id)) ENGINE=InnoDB
github仓库:https://github.com/yijixin66/FromZerotoExpert
服务器:http://8.142.128.17/FromZerotoExpert/register.html
1、ac自动机
2、sql语句
GitHub地址:https://github.com/lei342345795/FromZerotoExpert
1、
2、
create table disallow_word(
id int primary key auto_increment,
value varchar(255) not null,
type int default 0
);
github地址:https://github.com/Egofir/ferry
1、请把你的 敏感词 过滤的算法代码写在下面
Trie树:
校验器
2、建表语句也写下面。
GitHub链接: https://github.com/lucca-suen/FromZerotoExpert/tree/v2.2
1.敏感词的util类代码:
2.敏感词的建表语句
3.github地址
1.敏感词过滤代码。
我是在一个工具类VaildUtil中声明了一个前缀树的根节点的静态变量
然后在类中的isVaildName()方法中调用trie.startIndex来检查昵称是否包括敏感词
另外,为了后期能更好地维护已建立的前缀树,可以新建一个Controller层的类对disallow_word表进行CRUD操作(我没有实现),我还添加了一个updateTrie()方法决定是否根据新表中的敏感词重构新的字典树,这个方法有点不行,万一你已经构建了几百万单词的前缀树,因为添加了一个,难道是再构建几百万+1的前缀树,所以我们可以新增一个addTrie方法,只向前缀树中新增单词而不重构,也可以新增一个deleteTrie方法,只向前缀树中删除单词。DisallowWordController层代码如下:
或者在向数据库中的disallow_word表进行添加和删除操作的同时也对前缀树进行跟新。
Trie树结构代码如下:
2.建表语句:
github地址:https://github.com/shuaishuaixi03/FromZerotoExpert/tree/dev
这考虑的很周到啊
应该还是有点不足的,做时思考了部分时间
微信没找到你。。关于”在前缀树中删除一个字符串”我有一点疑问,在你的算法中:若要删除的字符串在Trie中的尾节点没有子节点,则只删除这个尾结点,同时这个尾结点对应的isEnd标志也删除了,但是要删除的字符串除了尾结点其它还在Trie中,也就是没删干净,即使这样在后续的逻辑判断中是没问题的,但也造成了空间浪费;且在极端情况下,假如删除了一个很长的敏感词,而给出的字符串只与这个敏感词差一个字,即使最后的结果是没有这个敏感词,相比于完全删除这个字符串,搜索的时间长了。
是有点问题,我当初考虑到前缀树中有ab,abc,acf,abe,abd,若是只删除ab,却删除了a、b两个节点,那么后面的abc,acf,abe,abd都查不到。可以改进,找到第一个子节点中只包含要删除的目标字符串中的字符节点,删除这个节点及它的子节点,比如一颗前缀树包含abcdefg,ac,bc,此时要删除abcdefg,找到的节点应该为c,应该删除c这个节点及之后的节点d,e,f,g
我已经实现出来了?嘿嘿
但是这样是提高了查询的效率,却降低的插入的效率,我没删除的节点可以留下来为下次插入的字符串的做准备,比如我插入了abcd,后面删除了abcd,但只释放了d节点,后面我在插入abcf,省下了申请a、b、c的三个节点空间的时间,只需申请f节点的空间,并把加入到c节点的子节点中,把f节点的isEnd设为true.而且根据场景,敏感词的长度一般有限制,不会太长,就是说树的高度不会太高,这颗前缀树应该是矮胖型的。很长的敏感词应该很少或者不存在
对,那就是鱼和熊掌的问题了?
drop table if exists
disallow_word;create table
disallow_word(idbigint auto_increment not null,valuevarchar(50) not null comment '敏感字',typeint default(0) comment '类型',primary key (
id)) engine=innodb default charset=utf8mb4 comment='敏感词库';
insert into disallow_word(value) values ('尼玛');
insert into disallow_word(value) values ('站长');
insert into disallow_word(value) values ('国家领导人');
insert into disallow_word(value) values ('操');
insert into disallow_word(value) values ('lala');
服务器链接:http://124.223.184.187:8088/FromZerotoExpert
Github仓库链接:https://github.com/jiangyklala/FromZerotoExpert/tree/dev
1.敏感词过滤代码
在这里用到了@PostConstruct注解,目的是防止每次敏感词检测时都要访问数据库表建立字典树,使用@PostConstruct注解之后,只会在Controller加载完毕时访问一次敏感词数据库表,并完成字典树的建立,当需要进行敏感词检测时,将已经创建好的字典树对象传入敏感词过滤算法中,即可完成检测。
2.建表语句
DROP TABLE IF EXISTS disallow_word;
CREATE TABLE disallow_word(
id INT PRIMARY KEY AUTO_INCREMENT,
value varchar(255) NOT NULL,
type INT DEFAULT(0)
)ENGINE=INNODB;
INSERT INTO disallow_word(value) VALUES("尼玛");
INSERT INTO disallow_word(value) VALUES("站长");
INSERT INTO disallow_word(value) VALUES("国家领导人");
INSERT INTO disallow_word(value) VALUES("操");
注:在项目文件夹中含有from_zeroto_expert.sql文件,里面记录了所有建库的sql代码。
gitHub路径:https://github.com/Second6s9/FromZerotoExpert/tree/dev
gitHub防覆盖路径:https://github.com/Second6s9/FromZerotoExpert/tree/day07
服务器地址:http://39.101.66.57:8080/FromZerotoExpert/register
服务器地址换了:http://123.57.142.33:8088/FromZerotoExpert/