[HNOI2004]L语言 字典树 记忆化搜索

给出\(n\)个字符串作为字典,询问\(m\)个字符串,求每个字符串最远能匹配(字典中的字符串)到的位置

容易想到使用字典树维护字典,然后又发现不能每步一直贪心无脑取最长匹配,所以考虑\(dfs\)穷举情况,每次匹配到新字符串后,分两种情况,要么继续当前的匹配,要么完成当前匹配,开始进行下一个字符串的匹配。

但是这样显然会\(TLE\),于是考虑记忆化,注意到性质:对于一个当前搜到并且之前已经搜过的位置,这个位置上的答案与前面如何搜的无关,于是记忆化,标记当前是否搜过,如果搜过就不搜了,因为反正都一样。

AC Code:

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct nod{
bool hav;
int nxt[26];
}t[1000005];
int tot;
inline void add(string s){
int len=s.size(),rot=0;
for(int i=0;i<len;++i){
int cur=s[i]-'a';
if(t[rot].nxt[cur]!=0){
rot=t[rot].nxt[cur];
}else{
t[rot].nxt[cur]=++tot;
rot=tot;
}
}
t[rot].hav=1;
}
string s;
int len,ans;
bool hav[1000005];
void dfs(int pos){
if(pos>=len) return;
if(ans==len) return;
int rot=0;
for(int i=pos;i<len;++i){
int cur=s[i]-'a';
if(t[rot].nxt[cur]!=0){
rot=t[rot].nxt[cur];
if(t[rot].hav){
ans=max(ans, i+1);
pos=i+1;
if(!hav[i]){
dfs(i+1);
hav[i]=1;
}
}
}else{
ans=max(ans, pos);
return;
}
}
}
int n,m;
int main(){
ios::sync_with_stdio(0);
cin>>n>>m;
for(int i=1;i<=n;++i){
cin>>s;
add(s);
}
for(int i=1;i<=m;++i){
memset(hav, 0, sizeof(hav));
ans=0;
cin>>s;
len=s.size();
dfs(0);
cout<<ans<<endl;
}
return 0;
}

最新文章

  1. IOS开发基础知识--碎片14
  2. [分类算法] :朴素贝叶斯 NaiveBayes
  3. 二叉树节点个数题目[n0,n1,n2]
  4. android,NDK android.mk相关
  5. XML的文档声明
  6. HDU 3466
  7. 【Shell脚本学习15】shell printf命令:格式化输出语句
  8. 算法 后减前最大值,zt
  9. Android框架结构图
  10. 【转】jsoncpp在xcode中的使用
  11. Longest Consecutive Sequence hashset
  12. Avoid The Lakes
  13. Unity3D专访——真正的面试
  14. if-else案例–开关灯
  15. 44-0-STM32的CAN外设
  16. [SDOI2015]序列统计(多项式快速幂)
  17. 使用 for 循环
  18. SQL 去重 显示第一条数据 显示一条数据
  19. C# Emgu CV学习笔记二之图像读写的两种方法
  20. Linux Kernel源码浏览

热门文章

  1. docker xfs卡死
  2. vue的就地复用--- v-for与:key
  3. Luogu5307 [COCI2019] Mobitel 【数论分块】【递推】
  4. Advanced REST Client 的安装
  5. raspbian buster阿里镜像
  6. GRPC代替webapi Demo。
  7. js入门之DOM动态创建数据
  8. javascript原型原型链 学习随笔
  9. sql server动态分页
  10. 记录java+testng运行selenium(四)--- 运行代码