首页 > 其他分享 >P4407 [JSOI2009] 电子字典

P4407 [JSOI2009] 电子字典

时间:2024-12-19 21:32:04浏览次数:11  
标签:20 trie ll 电子字典 MAXN P4407 true JSOI2009 字典

题目大意

详细题目传送门

给出 \(n\) 个互不相同字典串 \(S_i\)。和 \(m\) 个匹配串 \(Q_i\)。如果有字典串 \(S_i=Q_i\),输出 \(-1\)。三种变换操作:

  1. 在 \(S_{i,j}\) 后添加任意一个字符
  2. 删除 \(S_{i,j}\)
  3. 将 \(S_{i,j}\) 改成任意一个字符。

求每一个匹配串如果只进行 \(1\) 次操作有几个可以匹配的字典串。

\(n,m\leq 10^4\)

\(|S_i|,|Q_i|\leq 20\)

所有字符串都只有小写字母。

思路

考虑字典树。

发现时间复杂度猜一下是 \(O(26m|Q|)\) 的。其实发现哈希应该就能做,但是作者考场上没有写出来哈希,于是在这里补一个字典树做法。

先将所有字典串插入字典树,并记录结尾结点。对于每一个匹配串考虑深搜,用 \(f(u,l,c)\) 表示当前考虑到了字典树的 \(u\) 节点,是第 \(l\) 位,\(c\) 表示是否已经修改过。

如果已经修改过就一直到尾去记录是不是一个字典串。

之后对于三种操作:

添加任意一个字符就是对于 \(u\),进入到字符 \(x\) 中也就是搜索 \(f(t_{u,x},l,\text{true})\)。修改操作就是 \(f(t_{u,x},l+1,\text{true})\)。如果还能删就到 \(f_{t_{u,Q_{i,l}},l+1,\text{true}}\)。当然也可以选择这一位不修改。

代码

#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
const ll MAXN=1e5+5;
ll trie[MAXN*20][26],tot,ed[MAXN*20];
void insert(string s){
    ll u=0;
    for(auto c:s){
        int x=c-'a';
        if(!trie[u][x]){
            trie[u][x]=++tot;
        }
        u=trie[u][x];
    }
    ed[u]=1;
}
string s;
bool vis[MAXN];
ll vu[MAXN],ans;
set<string>se;
void dfs(ll u,ll len,bool change){
    if(len==s.size()&&ed[u]){
        if(change&&!vis[u]){
            vu[++ans]=u;
            vis[u]=true;
        }
        return;
    }
    if(len>=s.size()){
        if(!change){
            for(int i=0;i<26;++i){
                if(!trie[u][i]){continue;}
                dfs(trie[u][i],len,true);
            }
        }
        return;
    }
    ll x=s[len]-'a';
    if(trie[u][x]){
        dfs(trie[u][x],len+1,change);
    }
    if(!change){
        dfs(u,len+1,true);
        for(int i=0;i<26;++i){
            if(!trie[u][i]){continue;}
            dfs(trie[u][i],len,true);
            dfs(trie[u][i],len+1,true);
        }
    }
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    ll n,Q;
    cin>>n>>Q;
    for(int i=1;i<=n;++i){
        cin>>s;
        se.insert(s);
        insert(s);
    }
    while(Q--){
        cin>>s;
        if(se.count(s)){
            cout<<-1<<endl;
            continue;
        }
        ans=0;
        dfs(0,0,false);
        if(ans<0){
            cout<<-1<<endl;
            continue;
        }
        cout<<ans<<endl;
        while(ans){
            vis[vu[ans]]=false;
            ans--;
        }
    }
    return 0;
}

标签:20,trie,ll,电子字典,MAXN,P4407,true,JSOI2009,字典
From: https://www.cnblogs.com/tanghg/p/18617955/solution-p4407

相关文章

  • P4407 [JSOI2009] 电子字典
    题目链接:https://www.luogu.com.cn/problem/P4407trie树+爆搜做法:对所有文本串建树。对于编辑距离要求的三种情况,分四类在trie树上爆搜即可。#definemaxn200010structtrie{intson[maxn][26];intcnt[maxn];intidx=0;map<string,bool>mm;intv......
  • 【题解】P4307 [JSOI2009] 球队收益 / 球队预算
    P4307[JSOI2009]球队收益/球队预算题解题目传送门题意简述一共有\(n\)个球队比赛,输了赢了都会有相应的支出,现在让你安排\(m\)场比赛的输赢,是总支出最少。思路首先看到最小支出,状态不好定义,直接费用流,启动!。后文如果没有特殊说明,边的费用均为\(0\)。考虑建图,其......
  • CF765F,CF1793F,JSOI2009:区间最接近的两数
    link:https://codeforces.com/contest/765/problem/F据说是典中典问题(出现三次了)题意:给一个序列\(a_1,\dots,a_n\),有\(m\)次询问,每次询问给\(l,r(1\leql<r\leqn)\)问\(\min_{l\leqs<t\leqr}|a_s-a_t|\)\(1\leqn,m\leq10^5,a_i\leq10^9\).思路这个做法还是很妙,想......
  • 洛谷P4407 电子词典
    读完这题我马上就想到了题解trie+dfs的爆搜解法,这种解法思维难度很低,算个模拟,很容易想到但是我们稍微计算一下复杂度,就可以发现达到了\(1e8\)级别(\(26*20*20*1e4\),即对于每一个待查字符串(\(1e4\)),枚举每一个位置(\(20\)),每一个位置枚举26个字母(\(26\)),然后再在trie树上匹配(\(20\)))害......
  • P4054 [JSOI2009] 计数问题
    二维树状数组板子,C[color][x][y] #include<bits/stdc++.h>usingnamespacestd;constintN=403,M=2e5+4;#defineintlonglongintA[N][N],c[101][N......
  • JSOI2009 题解
    Count二维树状数组板子题,开\(c\)个二维树状数组即可过。可以通过离线对每个权值单独操作做到只开一个二维树状数组。如果空间要求更紧的话可以cdq分治做到只开一个......
  • 拼多多 2020校招 多多的电子字典(字典树前缀搜索,DP)
    多多鸡打算造一本自己的电子字典,里面的所有单词都只由a和b组成。每个单词的组成里a的数量不能超过N个且b的数量不能超过M个。多多鸡的幸运数字是K,它打算把所有满足条件的......
  • P4054 [JSOI2009] 计数问题
    传送门二维树状数组板子题(大概?)只要再多开一维\(c\)来存储该点的权值就可以了。这里的树状数组\(a[i][j][c]\)表示以第\(i\)行,第\(j\)列为右下角,权值为\(c\)的点......
  • P4407 [JSOI2009] 电子字典 题解
    题目:P4407这题差不多就是P1688的改版。参考一下我在P1688的做法,我们继续使用Hash,然后只要考虑如何去重就好了。于是就有了这个暴力的想法:#代表修改,@代表添加,$代......
  • luoguP4407 [JSOI2009] 电子字典 解题报告
    传送门题意对于多个字符串,查询其在字典树上的存在性或删除/插入/替换一个字符后存在的个数。思路存在性好说,直接在Trie树上做一遍查找即可。那剩下的三个操作怎么办......