题目链接

题意 : 给出 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. js判断设备,跳转app应用、android市场或者AppStore

    js移动设备判断方法大全 <!DOCTYPE html> <html> <head> <meta charset="UTF-8" > ...

  2. leecode刷题(28)-- 二叉树的前序遍历

    leecode刷题(28)-- 二叉树的前序遍历 二叉树的前序遍历 给定一个二叉树,返回它的 前序 遍历. 示例: 输入: [1,null,2,3] 1 \ 2 / 3 输出: [1,2,3] 思路 ...

  3. WPF使用资源图片

    一.加载本项目的图片 WPF引入了统一资源表示Uri来标识和访问资源.其中较为常见的情况是用Uri加载图像.Uri表达式的一把形式为:协议+授权+路径 协议:pack:// 授权:有两种,一种用于访问 ...

  4. 第二章 单表查询 T-SQL语言基础(2)

    单表查询(2) 2.2 谓词和运算符 T-SQL有几种不同的语言元素可以指定逻辑表达式,例如,查询过滤器(WHERE和HAVING),CHECK约束,等等. 在逻辑表达式中可以使用各种谓词(取值为TR ...

  5. 移动端实1px细线方法

    前言 在移动端中,宽度100%,1px的线看起来要比pc端中宽度100%,1px的线粗, 那是因为css中的1px并不等于移动设备(物理像素)的1px.物理像素显示是1个像素代表2个像素,所以出现为2 ...

  6. vm文件

    <html> <head> <title>编队管理</title> </head> <style type="text/cs ...

  7. php enum 数字类型插入失败的解决办法

    今天遇到一个问题,我设置mysql字段 existence 为enum ,值为 ''0','1'. 当使用 php 进行查找 where existence = 1 的时候,并没有查询出什么数据. 后 ...

  8. LintCode 64---合并排序数组

    public class Solution { /* * @param A: sorted integer array A which has m elements, but size of A is ...

  9. 26 Python模块之paramiko

    paramiko模块提供了ssh及sft进行远程登录服务器执行命令和上传下载文件的功能.这是一个第三方的软件包,使用之前需要安装. 1. 基于用户名和密码的sshclient方式登录 #创建一个ssh ...

  10. a标签的download属性

    a标签加上downlaod属性后,就可完成对href属性链接文件的下载,但仅仅是限于同源文件,如果是非同源,download属性会失效. 无download属性的时候,a标签的默认行为是链接跳转进行预 ...