Java项目中过滤敏感词

在现代社交网络和在线平台中,过滤敏感词是一项很重要的任务。不论是在聊天应用、社交媒体、论坛还是评论系统中,都需要对用户输入的内容进行过滤,以确保平台上的内容安全和健康。本文将介绍如何在 Java 项目中实现敏感词过滤,并提供一些代码示例。

使用 Trie 树

要过滤敏感词,可以使用一种称为 Trie 树的数据结构。Trie 树,也称为字典树或前缀树,是一种用于快速检索字符串的树形数据结构。它允许快速的插入和查找操作,特别适合用于敏感词过滤。

Trie 树的基本思想是将字符串拆分为字符,并将每个字符作为树的节点。每个节点可以有多个子节点,代表不同的字符可能。在 Trie 树中,从根节点到叶子节点的路径表示一个完整的字符串。如果某个节点被标记为结束节点,表示从根节点到该节点的路径组成了一个敏感词。

实现 Trie 树

首先,我们需要定义 Trie 树的节点类:

class TrieNode {
    private Map<Character, TrieNode> children;
    private boolean isEndOfWord;
    
    public TrieNode() {
        children = new HashMap<>();
        isEndOfWord = false;
    }
    
    public Map<Character, TrieNode> getChildren() {
        return children;
    }
    
    public boolean isEndOfWord() {
        return isEndOfWord;
    }
    
    public void setEndOfWord(boolean endOfWord) {
        isEndOfWord = endOfWord;
    }
}

接下来,我们可以定义 Trie 树的主要类:

class Trie {
    private TrieNode root;
    
    public Trie() {
        root = new TrieNode();
    }
    
    public void insert(String word) {
        TrieNode current = root;
        
        for (int i = 0; i < word.length(); i++) {
            char ch = word.charAt(i);
            TrieNode node = current.getChildren().get(ch);
            
            if (node == null) {
                node = new TrieNode();
                current.getChildren().put(ch, node);
            }
            
            current = node;
        }
        
        current.setEndOfWord(true);
    }
    
    public boolean search(String word) {
        TrieNode current = root;
        
        for (int i = 0; i < word.length(); i++) {
            char ch = word.charAt(i);
            TrieNode node = current.getChildren().get(ch);
            
            if (node == null) {
                return false;
            }
            
            current = node;
        }
        
        return current.isEndOfWord();
    }
}

过滤敏感词

使用 Trie 树实现敏感词过滤的核心思想是将待过滤的文本逐个字符与 Trie 树进行匹配。如果匹配成功,说明遇到了一个敏感词;如果匹配失败,说明该字符不是敏感词的一部分。我们可以使用递归的方式来实现这一过程。

下面是一个简单的敏感词过滤示例:

class WordFilter {
    private Trie trie;
    
    public WordFilter() {
        trie = new Trie();
    }
    
    public void addWord(String word) {
        trie.insert(word);
    }
    
    public String filter(String text) {
        StringBuilder filteredText = new StringBuilder();
        int start = 0;
        
        for (int i = 0; i <= text.length(); i++) {
            if (i == text.length() || !Character.isLetter(text.charAt(i))) {
                String word = text.substring(start, i);
                
                if (trie.search(word)) {
                    filteredText.append(replaceWithAsterisks(word));
                } else {
                    filteredText.append(word);
                }
                
                if (i < text.length()) {
                    filteredText.append(text.charAt(i));
                }
                
                start = i + 1;
            }
        }
        
        return filteredText.toString();
    }
    
    private String replaceWithAsterisks(String word) {
        StringBuilder asterisks = new StringBuilder();
        
        for (int i = 0; i < word.length(); i++) {
            asterisks.append("*");
        }
        
        return asterisks.toString();
    }
}

在上述示例中,WordFilter 类使用了前面定义的 Trie 树。