PHP melaksanakan penapisan perkataan haram (analisis algoritma)

藏色散人
Lepaskan: 2023-04-11 08:04:02
ke hadapan
3196 orang telah melayarinya

Pengenalan Algoritma

Bina kata kunci ke dalam pokok dan setiap perkataan ialah nod.

Lintas pernyataan yang perlu ditapis, dan cari setiap perkataan pernyataan dalam pokok untuk melihat sama ada ia wujud.

Kesukaran dalam pelaksanaan

Membina pokok adalah mudah. ​​Perkara utama ialah melintasi rentetan dalam php memerlukan anda memperoleh panjang satu aksara dengan betul. .
Kaedah hanya melintasi rentetan adalah seperti berikut:

$strLen = mb_strlen($str);
for ($i = 0; $i < $strLen; $i++) {
    echo mb_substr($str, $i, 1, "utf8"),PHP_EOL;
}
Salin selepas log masuk

Kaedah ini menggunakan siri mb_* fungsi untuk memintas dengan betul setiap aksara Ia sangat perlahan apabila memproses sejumlah besar rentetan . Tekaan saya ialah: mb_substrSetiap kali aksara dipintas, bilangan aksara sebelum rentetan mesti dikira.
Cara yang betul untuk melintasi rentetan ialah memintas rentetan mengikut peraturan pengekodan utf8 Sila lihat di bawah untuk mendapatkan butiran.

Pelaksanaan Algoritma

<?php
/**
 * 非法关键词检查
 */
class SensitiveWords
{
    protected $tree = null;
    protected $callIsNumeric = true;
    /**
     * 非法词汇列表,一个非法词汇占用一行
     */
    public function __construct($path = __DIR__ . &#39;/sensitiveWords.txt&#39;)
    {
        $this->tree = new WordNode();
        $file = fopen($path, "r");
        while (!feof($file)) {
            $words = trim(fgets($file));
            if ($words == &#39;&#39;) {
                continue;
            }
            //存在纯数字的非法词汇
            if (is_numeric($words)) {
                $this->callIsNumeric = false;
            }
            $this->setTree($words);
        }
        fclose($file);
    }

    protected function setTree($words)
    {
        $array = $this->strToArr($words);
        $tree = $this->tree;
        $l = count($array) - 1;
        foreach ($array as $k => $item) {
            $tree = $tree->getChildAlways($item);
            if ($l == $k) {
                $tree->end = true;
            }
        }
    }

    /**
     * 返回包含的非法词汇
     * @param string $str
     * @return array
     */
    public function check($str)
    {
        //先压缩字符串
        $str = trim(str_replace([&#39; &#39;, "\n", "\r"], [&#39;&#39;, &#39;&#39;, &#39;&#39;], $str));
        $ret = [];
        loop:
        $strLen = strlen($str);
        if ($strLen === 0) {
            return array_unique($ret);
        }
        //非法词汇中没有纯数字的非法词汇,待检测字符串又是纯数字的,则跳过不再检查
        if ($this->callIsNumeric && is_numeric($str)) {
            return array_unique($ret);
        }
        //挨个字符进行判断
        $tree = $this->tree;
        $words = &#39;&#39;;
        for ($i = 0; $i < $strLen; $i++) {
            //unicode范围 --> ord 范围
            //一字节 0-127 --> 0 - 127
            //二字节 128-2047 --> 194 - 223
            //三字节 2048-65535 --> 224 - 239
            //四字节 65536-1114111 --> 240 - 244
            //@see http://shouce.jb51.net/gopl-zh/ch3/ch3-05.html
            $ord = ord($str[$i]);
            if ($ord <= 127) {
                $word = $str[$i];
            } elseif ($ord <= 223) {
                $word = $str[$i] . $str[$i + 1];
                $i += 1;
            } elseif ($ord <= 239) {
                $word = $str[$i] . $str[$i + 1] . $str[$i + 2];
                $i += 2;
            } elseif ($ord <= 244) {
                //四字节
                $word = $str[$i] . $str[$i + 1] . $str[$i + 2] . $str[$i + 3];
                $i += 3;
            } else {
                //五字节php都溢出了
                //Parse error: Invalid UTF-8 codepoint escape sequence: Codepoint too large
                continue;
            }
            //判断当前字符
            $tree = $tree->getChild($word);
            if (is_null($tree)) {
                //当前字不存在,则截取后再次循环
                $str = substr($str, $i + 1);
                goto loop;
            } else {
                $words .= $word;
                if ($tree->end) {
                    $ret[] = $words;
                }
            }
        }
        return array_unique($ret);
    }

    protected function strToArr($str)
    {
        $array = [];
        $strLen = mb_strlen($str);
        for ($i = 0; $i < $strLen; $i++) {
            $array[] = mb_substr($str, $i, 1, "utf8");
        }
        return $array;
    }
}
/**
 * 单个字符的节点
 */
class WordNode
{
    //是否为非法词汇末级节点
    public $end = false;
    //子节点
    protected $child = [];

    /**
     * @param string $word
     * @return WordNode
     */
    public function getChildAlways($word)
    {
        if (!isset($this->child[$word])) {
            $this->child[$word] = new self();
        }
        return $this->child[$word];
    }

    /**
     * @param string $word
     * @return WordNode|null
     */
    public function getChild($word)
    {
        if ($word === &#39;&#39;) {
            return null;
        }
        if (isset($this->child[$word])) {
            return $this->child[$word];
        }
        return null;
    }
}
Salin selepas log masuk

Pembelajaran yang disyorkan: "Tutorial Video PHP"

Atas ialah kandungan terperinci PHP melaksanakan penapisan perkataan haram (analisis algoritma). Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Label berkaitan:
php
sumber:learnku.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan