力扣745.前缀和后缀搜索

本文探讨了两种方法实现字符串搜索:一种是利用前缀树和后缀树,另一种是哈希表。在前缀树和后缀树方法中,每个树节点存储经过该节点的所有编号,但这种方法导致超时。后来通过记忆化搜索优化,但仍然超时。最终,作者转向使用哈希表,发现其更有效率。哈希表法通过将单词的前后缀组合连接成键,快速查找最大下标。总结了这两种方法在处理大量字符串时的优缺点,并提出进一步优化的可能。
摘要由CSDN通过智能技术生成

一.字典树

用了两种方法做,首先想到得是构造两颗树,一颗前缀树,一颗后缀树,树节点是一个结构体,储存着经过这个节点得所有编号,因为是顺序向树中添加节点,最后就是最大的,可以通过遍历两颗树得到两份链表,最后通过双指针从后往前找,第一个相同的就是最大的下标。

最后结果超时了,加入了一部分记忆化搜索,每一次找完就把这对前缀和后缀加入到一个链表里,下一次先在链表中找,没有在去树中找,最后还是超时了。后面学了第二种哈希表法,发现这个记忆化搜索有些问题,可以使用哈希表,有机会可以在做一次,优化一下。

struct tree
{
    vector<int>  id;

    int  next[27];
    tree() {
        memset(next, 0, sizeof(next));
    }
   

};
struct jiji
{
    string st1;
    string st2;
    int a;
    
};
class WordFilter {
public:
    vector<jiji> ji1;
    tree front[100100];
    int a;
    tree last[100100];
    int b;
    WordFilter(vector<string>& words) {
        //建一颗前缀树,一颗后缀树
        //树的节点上保留这个前缀的所有结点的信息
        //前后缀树各能得到一份id
        //从后向前,双指针找出相同的最大的id

        a = 0;
        b = 0;
        for (int i = 0; i < words.size(); i++)
        {
            int ptemp = 0;
            for (int j = 0; j < words[i].length(); j++)
            {
                if (front[ptemp].next[words[i][j] - 'a'] == 0)
                {
                    front[ptemp].next[words[i][j] - 'a'] = ++a;
                    ptemp = a;
                    front[ptemp].id.push_back(i);
                }
                else
                {
                    ptemp = front[ptemp].next[words[i][j] - 'a'];
                    front[ptemp].id.push_back(i);
                }
            }

        }

        for (int i = 0; i < words.size(); i++)
        {
            int ptemp = 0;
            for (int j = words[i].length() - 1; j >= 0; --j)
            {
                if (last[ptemp].next[words[i][j] - 'a'] == 0)
                {
                    last[ptemp].next[words[i][j] - 'a'] = ++b;
                    ptemp = b;
                    last[ptemp].id.push_back(i);
                }
                else
                {
                    ptemp = last[ptemp].next[words[i][j] - 'a'];
                    last[ptemp].id.push_back(i);
                }
            }

        }


    }

    int f(string pref, string suff) {
        for(int i = 0;i < ji1.size() ;i ++)
        {
            if(ji1[i].st1 == pref && ji1[i].st2 == suff)
            {
                return ji1[i].a;
            }
        }
        int fr = 0;
        int las = 0;
        int ptemp = 0;
        for (int i = suff.length() - 1; i >= 0; --i)//后缀树得到id
        {
            if (last[ptemp].next[suff[i] - 'a'] != 0)
            {
                ptemp = last[ptemp].next[suff[i] - 'a'];
                if (i == 0)
                {
                    //las = last[ptemp].id;
                    las = ptemp;
                }
            }
            else
                break;
        }

        
        ptemp = 0;
        for (int i = 0; i < pref.length(); i++)//前缀树得到id
        {
            if (front[ptemp].next[pref[i] - 'a'] != 0)
            {
                ptemp = front[ptemp].next[pref[i] - 'a'];
                if (i == pref.length() - 1)
                {
                    //fr = front[ptemp].id;
                    fr = ptemp;
                }
            }
            else
                break;
        }
       

        int lef = (front[fr]).id.size() - 1;
        int rig = (last[las]).id.size() - 1;
        while (lef >= 0 && rig >= 0)
        {
            if (front[fr].id[lef] > last[las].id[rig])
            {
                lef--;
            }
            else if (front[fr].id[lef] < last[las].id[rig])
            {
                rig--;
            }
            else
            {
                jiji ko;
                ko.st1 = pref;
                ko.st2 = suff;
                ko.a =  front[fr].id[lef];
                ji1.push_back(ko);
                return front[fr].id[lef];

            }
               
        }
         jiji ko;
        ko.st1 = pref;
        ko.st2 = suff;
        ko.a = -1;
        ji1.push_back(ko);
        return -1;
    }
};
/**
 * Your WordFilter object will be instantiated and called as such:
 * WordFilter* obj = new WordFilter(words);
 * int param_1 = obj->f(pref,suff);
 */

二.哈希表

用特殊字符把一个单词的前后缀的所有组合连在一起,找的时候同样讲前后缀拼接在一起,进行查询

class WordFilter {
public:
    unordered_map<string, int> mmap;
    //通过哈希表储存一个单词的所有前后缀的可能,后面int对应最大下标
    WordFilter(vector<string>& words) {
        //特殊字符连接构件哈希表
        auto ite = words.begin();
        int ant = 0;
        while (ite != words.end())
        {
            int m = (*ite).length();
            for (int i = 1; i <= m; i++)
            {
                for (int j = m; j >= 0; j--)
                {
                    string str = (*ite).substr(0, i) + "#" + (*ite).substr(m - j, j);
                    mmap[str] = ant;
                }
            }
            ant++;
            ite++;
        }
    }

    int f(string pref, string suff) {
        string str = pref + "#" + suff;
        return mmap.count(str) ? mmap[str] : -1;
    }
};

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值