tire 学习心得

一、碎语&心得

       下一周我准备学习 AC 自动机(这个名字是真的喜感不知道为什么要叫做 AC 自动机)。所以我要先学他的前置条件字典树,因为已经有了用数组模拟树的经验,再加上树也学了不少了而且字典树很简单。所以我的学习没有遇到什么困难,花了半个小时看了一会儿模板,在搞懂了几个关键点之后我就写出来了,代码量也比较小,在一些特定问题中对程序运行速度的优化也非常优秀,据我所知这个数据结构经常被用于搜索引擎,这个数据结构具有简单好用,代码量小,这两个优点,像树状数组一样。。而且查找只和字符串长度相关,与 n 无关,在数据量大且单词长度不长的情况下,肯定会比平衡查找树还优秀。

      虽然是我的心得但原理还是稍微记一下,到时候方便复习,而且万一有大佬浏览蒟蒻的心得呢,图就不配了(其实就是太麻烦了懒得整)。

二、实现原理

     字典树其实是一颗根节点不存放数据的树,每个节点至多有 26 个孩子(用于字符串只包含 26 个字母的情况,当然大部分时候都是运用这种情况)他的原理就好像查字典一样,你要查 apple,肯定首先翻到 a 那一块去,然后在翻到第二个字母是 p 的那一页去等等等等。表现在代码里就是查找根节点有没有挂着 a 这个节点,再看 a 下面有没有挂着 p 这个节点。插入也同理,一个字母一个字母的来新建节点,如果已经建立了,那就直接跳过就行了,在查找时还要注意一件事,那就是标记挂着最后一个字母的节点为结束节点(其实字母挂在边上),不然插入 apple 之后查找 ap 也会返回真。

三、代码

头文件和主函数根本不重要就贴个类吧。

c++代码:

 

template<int T>
class trie
{
private:
    int tree[T][30],cnt;
    bitset<T>mark;
public:
    void insert(string a)
    {
        int r = 0;
        for(int i=0;i<a.size();i++)
        {
            int x = a[i]-'a';
            if(tree[r][x] == 0)
            {
                tree[r][x] = ++cnt;
            }
            r = tree[r][x];
        }
        mark[r] = 1;
    }
    bool find(string a)
    {
        int r = 0;
        for(int i=0;i<a.size();i++)
        {
            int x = a[i]-'a';
            if(tree[r][x] == 0)
            {
                return false;
            }
            r = tree[r][x];
        }
        return mark[r];
    }
    trie()
    {
        cnt = 0;
    }
};

 

因为我还在学习 java,所以我同时也用 java 写了一遍。

java代码:

public class trie 
{
    private int[][] tree;
    private int cnt;
    private boolean[] mark;
    public trie(int size)
    {
        tree = new int[200010][size];
        mark = new boolean[200010];
        cnt = 0;
    }
    public void insert(String s)
    {
        int r = 0;
        for(int i = 0;i < s.length();i++)
        {
            int x = s.charAt(i) - 'a';
            if(tree[r][x] == 0)
            {
                tree[r][x] = ++cnt;
            }
            r = tree[r][x];
        }
        mark[r] = true;
    }
    public boolean find(String s)
    {
        int r = 0;
        for(int i = 0;i < s.length();i++)
        {
            int x = s.charAt(i) - 'a';
            if(tree[r][x] == 0)
            {
                return false;
            }
            r = tree[r][x];
        }
        return mark[r];
    }
}

同时还顺带学习了一下 java 的字符串和二维数组,java 没有重载运算符不能像数组一样用字符串类真的不方便,但是却能很好的区分数组和类,也算是有利有弊吧。

有了这个下周我就可以学 AC 自动机了,想想还是挺兴奋的。

 

posted @ 2020-03-08 13:29  你非阳光但却暖我心  阅读(190)  评论(1编辑  收藏  举报