题目链接

题意 : 给出 n 个串、然后给出一个问询串、问你对于问询串的每一个前缀、需要至少补充多少单词才能使得其后缀包含 n 个串中的其中一个、注意 '-' 字符代表退格

分析 :

多串的匹配问询自然想到 AC 自动机 或者 构建 Trie 图

首先将 N 个串丢到 Trie 图里面

对于每一个节点记录其要变成一个完整的串最少需要补充的单词数

然后在问询的时候、由于有退格操作

于是需要将跑过的节点路径记录下来以便恢复

这个我们可以使用栈来做到

然后对于问询串的每一个前缀问询

可以采用 DP 的方式来一直记录跳 Fail 时候每个节点的最优值是什么

#include<bits/stdc++.h>
#define LL long long
#define ULL unsigned long long

#define scl(i) scanf("%lld", &i)
#define scll(i, j) scanf("%lld %lld", &i, &j)
#define sclll(i, j, k) scanf("%lld %lld %lld", &i, &j, &k)
#define scllll(i, j, k, l) scanf("%lld %lld %lld %lld", &i, &j, &k, &l)

#define scs(i) scanf("%s", i)
#define sci(i) scanf("%d", &i)
#define scd(i) scanf("%lf", &i)
#define scIl(i) scanf("%I64d", &i)
#define scii(i, j) scanf("%d %d", &i, &j)
#define scdd(i, j) scanf("%lf %lf", &i, &j)
#define scIll(i, j) scanf("%I64d %I64d", &i, &j)
#define sciii(i, j, k) scanf("%d %d %d", &i, &j, &k)
#define scddd(i, j, k) scanf("%lf %lf %lf", &i, &j, &k)
#define scIlll(i, j, k) scanf("%I64d %I64d %I64d", &i, &j, &k)
#define sciiii(i, j, k, l) scanf("%d %d %d %d", &i, &j, &k, &l)
#define scdddd(i, j, k, l) scanf("%lf %lf %lf %lf", &i, &j, &k, &l)
#define scIllll(i, j, k, l) scanf("%I64d %I64d %I64d %I64d", &i, &j, &k, &l)

#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define lowbit(i) (i & (-i))
#define mem(i, j) memset(i, j, sizeof(i))

#define fir first
#define sec second
#define VI vector<int>
#define ins(i) insert(i)
#define pb(i) push_back(i)
#define pii pair<int, int>
#define VL vector<long long>
#define mk(i, j) make_pair(i, j)
#define all(i) i.begin(), i.end()
#define pll pair<long long, long long>

#define _TIME 0
#define _INPUT 0
#define _OUTPUT 0
clock_t START, END;
void __stTIME();
void __enTIME();
void __IOPUT();
using namespace std;

;
;
;

struct Aho{
    struct StateTable{
        int nxt[Letter];
        int fail, cnt, dis;
        bool vis;
        void init(){
            memset(nxt, , sizeof(nxt));
            fail = ;
            cnt = ;
            dis = 0x3f3f3f3f;
            vis = false;
        }
    }Node[max_node];

    int sz;
    queue<int> que;

    inline ].init(); sz = ; }

    inline void insert(char *s, int len){
        ;
        Node[now].dis = min(Node[now].dis, len);
        ; i<len; i++){
            int idx = s[i] - 'a';
            if(!Node[now].nxt[idx]){
                Node[sz].init();
                Node[now].nxt[idx] = sz++;
            }
            now = Node[now].nxt[idx];
            Node[now].dis = min(Node[now].dis, len-i-);
        }
        Node[now].cnt++;
    }

    inline void build(){
        Node[].fail = -;
        que.push();
        while(!que.empty()){
            int top = que.front();  que.pop();
            ; i<Letter; i++){
                if(Node[top].nxt[i]){
                    ) Node[ Node[top].nxt[i] ].fail = ;
                    else{
                        int v = Node[top].fail;
                        ){
                            if(Node[v].nxt[i]){
                                Node[ Node[top].nxt[i] ].fail = Node[v].nxt[i];
                                break;
                            }v = Node[v].fail;
                        }) Node[ Node[top].nxt[i] ].fail = ;
                    }que.push(Node[top].nxt[i]);
                }?Node[ Node[top].fail ].nxt[i]:;
            }
        }
    }

//    int Match(char *s){
//        int now = 0, res = 0;
//        for(int i=0; s[i]!='\0'; i++){
//            int idx = s[i] - 'a';
//            now = Node[now].nxt[idx];
//            int tmp = now;
//            while(tmp != 0){
//                res += Node[tmp].cnt;
//                Node[tmp].cnt = 0;
//                tmp = Node[tmp].fail;
//            }
//        }
//        return res;
//    }

    int dp[max_node];
    int GetDP(int cur){
        ) return Node[cur].dis;
        ) return dp[cur];
        dp[cur] = min(Node[cur].dis, GetDP(Node[cur].fail));
        return dp[cur];
    }
    void query(char *s, int len){
        ;
        memset(dp, -, sizeof(dp));
        stack<int> pos;
        printf("%d\n", Node[now].dis);
        ; i<len; i++){
            if(s[i] == '-'){
                if(!pos.empty()) pos.pop();
                ;
                else now = pos.top();
            }else{
                int idx = s[i] - 'a';
                now = Node[now].nxt[idx];
                pos.push(now);
            }

            int ans = Node[now].dis;
            ans = min(ans, GetDP(now));

            printf("%d\n", ans);
        }
    }
}ac;

char s[max_len];
int main(void){__stTIME();__IOPUT();

    int n;

    sci(n);

    ac.init();

    ; i<n; i++){
        scs(s);
        ac.insert(s, strlen(s));
    }

    ac.build();

    scs(s);

    ac.query(s, strlen(s));

__enTIME();;}

void __stTIME()
{
    #if _TIME
        START = clock();
    #endif
}

void __enTIME()
{
    #if _TIME
        END = clock();
        cerr<<"execute time = "<<(double)(END-START)/CLOCKS_PER_SEC<<endl;
    #endif
}

void __IOPUT()
{
    #if _INPUT
        freopen("in.txt", "r", stdin);
    #endif
    #if _OUTPUT
        freopen("out.txt", "w", stdout);
    #endif
}

Nowcoder Typing practice ( Trie 图 )的更多相关文章

  1. 【BZOJ-2938】病毒 Trie图 + 拓扑排序

    2938: [Poi2000]病毒 Time Limit: 1 Sec  Memory Limit: 128 MBSubmit: 609  Solved: 318[Submit][Status][Di ...

  2. 【hihoCoder】1036 Trie图

    题目:http://hihocoder.com/problemset/problem/1036 给一个词典dict,词典中包含了一些单词words.要求判断给定的一个文本串text中是否包含这个字典中 ...

  3. 【hihoCoder 1036】Trie图

    看了一下简单的$Trie图$,调模板调啊调一连调了$2h$,最后发现$-'a'$打成$-'A'$了hhh,有种摔键盘的冲动. $Trie图$是$Trie树$上建立“前缀边”,不用再像在$Trie树$上 ...

  4. 字符串 --- KMP Eentend-Kmp 自动机 trie图 trie树 后缀树 后缀数组

    涉及到字符串的问题,无外乎这样一些算法和数据结构:自动机 KMP算法 Extend-KMP 后缀树 后缀数组 trie树 trie图及其应用.当然这些都是比较高级的数据结构和算法,而这里面最常用和最熟 ...

  5. Trie图和Fail树

    Trie图和AC自动机的区别 Trie图是AC自动机的确定化形式,即把每个结点不存在字符的next指针都补全了.这样做的好处是使得构造fail指针时不需要next指针为空而需要不断回溯. 比如构造ne ...

  6. hdu2457 Trie图+dp

    hdu2457 给定n个模式串, 和一个文本串 问如果修改最少的字符串使得文本串不包含模式串, 输出最少的次数,如果不能修改成功,则输出-1 dp[i][j] 表示长度为i的字符串, 到达状态j(Tr ...

  7. Trie图

    AC自动机是KMP的多串形式,当文本串失配时,AC自动机的fail指针告诉我们应该跳到哪里去继续匹配(跳到当前匹配串的最长后缀去),所以AC自动机的状态是有限的 但是AC自动机具有不确定性, 比如要求 ...

  8. CF 291E. Tree-String Problem [dfs kmp trie图优化]

    CF291E 题意:一棵树,每条边上有一些字符,求目标串出现了多少次 直接求目标串的fail然后一边dfs一边跑kmp 然后就被特殊数据卡到\(O(n^2)\)了... 因为这样kmp复杂度分析的基础 ...

  9. AC自动机相关Fail树和Trie图相关基础知识

    装载自55242字符串AC自动机专栏 fail树 定义 把所有fail指针逆向,这样就得到了一棵树 (因为每个节点的出度都为1,所以逆向后每个节点入度为1,所以得到的是一棵树) 还账- 有了这个东西, ...

随机推荐

  1. 2019牛客暑期多校训练营(第二场)-H Second Large Rectangle(次大子矩阵,降维,直方图+单调栈)

    题目链接:https://ac.nowcoder.com/acm/contest/882/H 题目:给n×m的由01组成的矩阵,求次大全1子矩阵的大小. 思路:第一步还是降维操作,用a[i][j]记录 ...

  2. [转帖]linux中systemctl详细理解及常用命令

    linux中systemctl详细理解及常用命令 2019年06月28日 16:16:52 思维的深度 阅读数 30 https://blog.csdn.net/skh2015java/article ...

  3. (5.1)mysql高可用系列——高可用架构方案概述

    关键词:mysql高可用概述,mysql高可用架构 常用高可用方案 20190918 现在业内常用的MySQL高可用方案有哪些?目前来说,用的比较多的开源方案分内置高可用与外部实现,内置高可用有如下: ...

  4. 自然语言处理工具pyhanlp分词与词性标注

    Pyhanlp分词与词性标注的相关内容记得此前是有分享过的.可能时间太久记不太清楚了.以下文章是分享自“baiziyu”所写(小部分内容有修改),供大家学习参考之用. 简介 pyhanlp是HanLP ...

  5. java-selenium-java鼠标键盘操作Actions类和Robot

    Actions类 一.鼠标右击.双击 Java代码 //定位百度首页右上角 新闻 WebElement Xw=driver.findElement(By.xpath("//*[@id='u1 ...

  6. Luogu P3810 【模板】三维偏序(陌上花开)(CDQ分治)

    题目 以三维偏序为例来讲一下CDQ分治. CDQ的本质就是把一个序列分成两段,计算左边对右边的贡献,然后分治. 不过一般都是先分治到底再从下往上算,这样可以先归并再算. 比如这道题,我们先按第一维排序 ...

  7. centos终端显示字母重叠

    在使用VMware虚拟机安装linux之后,之后调整了中文显示,但是后来不知道怎么回事在终端显示的字母很多都是重叠的. 在百度上也找到很多的解决办法 eg: 终端键入:vi /etc/fonts/co ...

  8. python并发编程-多线程实现服务端并发-GIL全局解释器锁-验证python多线程是否有用-死锁-递归锁-信号量-Event事件-线程结合队列-03

    目录 结合多线程实现服务端并发(不用socketserver模块) 服务端代码 客户端代码 CIL全局解释器锁****** 可能被问到的两个判断 与普通互斥锁的区别 验证python的多线程是否有用需 ...

  9. unittest之一框架、suite

    1.unittest是Python的标准库里的模块,所以在创建测试方法时,需直接导入unittest即可 2.unittest框架的六大模块: 测试用例TestCase 测试套件TestSuit:测试 ...

  10. python基础之函数进阶

    假如有一个函数,实现返回两个数中的较大值: def my_max(x,y): m = x if x>y else y return mbigger = my_max(10,20)print(bi ...