题目描述

标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的。现在你要处理的就是一段没有标点的文章。

一段文章T是由若干小写字母构成。一个单词W也是由若干小写字母构成。一个字典D是若干个单词的集合。我们称一段文章T在某个字典D下是可以被理解的,是指如果文章T可以被分成若干部分,且每一个部分都是字典D中的单词。

例如字典D中包括单词{‘is’, ‘name’, ‘what’, ‘your’},则文章‘whatisyourname’是在字典D下可以被理解的,因为它可以分成4个单词:‘what’, ‘is’, ‘your’, ‘name’,且每个单词都属于字典D,而文章‘whatisyouname’在字典D下不能被理解,但可以在字典D’=D+{‘you’}下被理解。这段文章的一个前缀‘whatis’,也可以在字典D下被理解,而且是在字典D下能够被理解的最长的前缀。

给定一个字典D,你的程序需要判断若干段文章在字典D下是否能够被理解。并给出其在字典D下能够被理解的最长前缀的位置。

输入格式

输入文件第一行是两个正整数n和m,表示字典D中有n个单词,且有m段文章需要被处理。之后的n行每行描述一个单词,再之后的m行每行描述一段文章。

其中1<=n, m<=20,每个单词长度不超过10,每段文章长度不超过1M。

输出格式

对于输入的每一段文章,你需要输出这段文章在字典D可以被理解的最长前缀的位置。

emmmmmm, 好多神奇的算法, 什么KMP, 什么trie树, 什么AC自动机, 但是都不会, 题解竟然没有hash, 还是用hash + dp, 随便搞一搞吧。。。

刚看到这道题的时候, 这不显然用hash;用s, t表示两个指针, 不断把t++, 如果\([s, t]\)这个区间能够满足, 就把s赋成t + 1, 最后输出s - 1, 然后。。。我就光荣的WA掉了。 不妨看这组数据:

a
abc aabc

假如用以上算法的话输出值为2, 即匹配了aa, 但整个文章显然都是可以翻译的, 所以上面贪心的思想就是不对的, 那怎么办呢。。。

首先我把每个单词的hash值求出来, 再用一次数字hash, 保证这个hash值能在我们存储的范围内。 并且我开一个vector, q[i]表示以i结尾的单词的hash值和长度。

在匹配的时候, 这\(f[i]\)表示前缀i是否能匹配, 我从1枚举到当前文章的长度len, 并枚举以当前字母结尾的hash值和长度len1, 当且仅当\(f[i - len1]\)能满足, 且\([i - len1 + 1, i]\)这个区间是一个单词, 那么\(f[i]\)就可以赋成true, 这样输出最后能够达到的长度即可。

#include <bits/stdc++.h>

using namespace std;

typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const int MAXM = 5e3 + 10;
const double eps = 1e-5; template < typename T > inline void read(T &x) {
x = 0; T ff = 1, ch = getchar();
while (!isdigit(ch)) {
if (ch == '-') ff = -1;
ch = getchar();
}
while (isdigit(ch)) {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
x *= ff;
} template < typename T > inline void write(T x) {
if (x == 0) {
putchar('0');
return ;
}
if (x < 0) putchar('-'), x = -x;
static T tot = 0, ch[30];
while (x) {
ch[++tot] = x % 10 + '0';
x /= 10;
}
while (tot) putchar(ch[tot--]);
} ull p[MAXN], vis[MAXN], sum[MAXN];
int n, m, f[MAXN];
char ch[MAXN];
const int mod = 1e6 + 7;
vector < pair < int, int > > q[30]; inline int H(ull x) {
int u = x % mod;
while (vis[u] && vis[u] != x) ++u;
return u;
} int main() {
read(n), read(m);
for (int i = 1; i <= n; ++i) {
scanf("%s", ch + 1);
int len = strlen(ch + 1);
ull cnt = 0;
for (int j = 1; j <= len; ++j) {
cnt = cnt * 131 + ch[j] - 'a' + 1;
}
int u = H(cnt);
vis[u] = cnt;
q[ch[len] - 'a' + 1].push_back({u, len});
}
p[0] = 1;
for (int i = 1; i <= MAXN; ++i) p[i] = p[i - 1] * 131;
while (m--) {
scanf("%s", ch + 1);
int len = strlen(ch + 1);
for (int i = 1; i <= len; ++i)
sum[i] = sum[i - 1] * 131 + ch[i] - 'a' + 1;
f[0] = 1;
int cnt = 0;
for (int i = 1; i <= len; ++i) {
f[i] = 0;
int x = ch[i] - 'a' + 1;
for (int j = 0; j < q[x].size(); ++j) {
int u = q[x][j].first, len1 = q[x][j].second;
if (i < len1) continue;
if (!f[i - len1]) continue;
ull v = sum[i] - sum[i - len1] * p[len1];
int h = H(v);
if (vis[h]) f[i] = 1, cnt = i;
}
}
write(cnt);
puts("");
}
return 0;
}

[HNOI2004]L语言 trie树? Ac自动机? hash!!的更多相关文章

  1. 【BZOJ1212】[HNOI2004]L语言 Trie树

    [BZOJ1212][HNOI2004]L语言 Description 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构 ...

  2. BZOJ1212[HNOI2004]L语言——trie树+DP

    题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构成.一个单词W也是由若干小写字母构成.一个字典D是若干个单词的 ...

  3. 2021.11.09 P2292 [HNOI2004]L语言(trie树+AC自动机)

    2021.11.09 P2292 [HNOI2004]L语言(trie树+AC自动机) https://www.luogu.com.cn/problem/P2292 题意: 标点符号的出现晚于文字的出 ...

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

    [HNOI2004]L语言 字典树 记忆化搜索 给出\(n\)个字符串作为字典,询问\(m\)个字符串,求每个字符串最远能匹配(字典中的字符串)到的位置 容易想到使用字典树维护字典,然后又发现不能每步 ...

  5. Luogu P2292 [HNOI2004]L语言(Trie+dp)

    P2292 [HNOI2004]L语言 题面 题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章 \(T\) 是由若干小写字母构成. ...

  6. BZOJ 1212 HNOI 2004 L语言 Trie树

    标题效果:给一些词.和几个句子,当且仅当句子可以切子可以翻译词典,这意味着该子将被翻译. 找到最长前缀长度可以被翻译. 思维:使用Trie树阵刷.你可以刷到最长的地方是最长的字符串可以翻译到的地方. ...

  7. 洛谷.2292.[HNOI2004]L语言(Trie DP)

    题目链接 /* 简单的DP,查找是否有字典中的单词时在Trie树上做 要注意在最初Match(0)一遍后,i还是要从0开始匹配,因为如果有长度为1的单词,Match(i+1)不会从1更新 1M=102 ...

  8. BZOJ1212: [HNOI2004]L语言(Trie图+DP)

    Description 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构成.一个单词W也是由若干小写字母构成.一个字典D ...

  9. BZOJ 1212: [HNOI2004]L语言 trie

    长度小于 10 是关键信息~ #include <cstdio> #include <cstring> #include <algorithm> #define N ...

随机推荐

  1. 针对媒体不实报道误导大众--抹黑C#工资垫底

    最近注意到一些媒体故意抹黑C# 工资垫底,参见 https://www.toutiao.com/i6741889572931633668/: 通过搜索引擎搜索<编程语言薪酬排行:Python薪资 ...

  2. JAVA线程基础概念及使用

    一.线程和进程的区别 在操作系统中所有运行的任务通常对应一个进程,进程是系统进行资源分配和调度的一个独立单位.线程是进程的组成部分,一个进程最少包含一个线程.并发和并行的区别是,并发指的在同一时刻内, ...

  3. 微项目:一步一步带你使用SpringBoot入门(一)

    最近放假了,休息的时候不忘写个小项目来玩玩. 如果有需要一起手动做项目的朋友可以和我一起做这个小项目. 做到哪随心所欲.也就一周的事哈哈. *** 开发环境 JDK1.8 JetBrain Intel ...

  4. Hibernate 中setResultTransformer使用

    在使用hibernate框架,查询数据库多张表或者单张表的某几个需要的字段数据时,往往只能通过sql语句配合setResultTransformer将查询到的数据封装到一个map集合中,再将map集合 ...

  5. maven 项目报错org.apache.ibatis.binding.BindingException: Invalid bound statement (not found)解决

    idea在使用maven构建的项目中使用mybatis时报错org.apache.ibatis.binding.BindingException: Invalid bound statement (n ...

  6. .Net Core 商城微服务项目系列(十):使用SkyWalking构建调用链监控(2019-02-13 13:25)

    SkyWalking的安装和简单使用已经在前面一篇介绍过了,本篇我们将在商城中添加SkyWalking构建调用链监控. 顺带一下怎么把ES设置为Windows服务,cd到ES的bin文件夹,运行ela ...

  7. Spring MVC学习 ( RESTful)

    是一套规则,不同的系统之间(Vue java Python C#  PHP)具体四种不同类型的HTTP 请求分别表示四种基本操作(CRUD) GET :查询(R) POST:添加(C) PUT:修改( ...

  8. Linux kail安装及查看命令

    Linux kail安装及查看命令  apt-get update                          //更新源 apt-get install package             ...

  9. gitblit在windows10上的安装及服务启动报错处理

    折腾一下午算是装好了,心情不错决定分享一下.安装步骤大同小异网上都有,主要是Failed creating java 这个报错,百度出来的没有一个能给我解决的,摸索半天找出一个自己的方式.为报错而来的 ...

  10. java之ReentrantLock详解

    前言 如果一个代码块被synchronized修饰了,当一个线程获取了相应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的释放,现在有这么一种情况,这个获取锁的线程由于要等待IO或者其他原 ...