题目描述

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

一段文章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可以被理解的最长前缀的位置。

输入输出样例

输入样例#1:
复制

4 3
is
name
what
your
whatisyourname
whatisyouname
whaisyourname
输出样例#1: 复制

14  (整段文章’whatisyourname’都能被理解)
6 (前缀’whatis’能够被理解)
0 (没有任何前缀能够被理解)

题解

为什么AC自动机没什么近乎模板的题写啊QAQ

在上古年代写过一个Trie+爆搜的代码↓

 /*
qwerta
P2292 [HNOI2004]L语言
Accepted
100
代码 C++,1.01KB
提交时间 2018-05-19 16:28:10
耗时/内存
832ms, 6812KB
*/
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
struct emm{
int z[];
bool en;
}a[];
char s[];
int f[];
int t=;
void build()
{
int d=strlen(s)-;
int e=;
while(d>=)
{
if(a[e].z[s[d]-])e=a[e].z[s[d]-];
else e=a[e].z[s[d]-]=++t;
d--;
}
a[e].en=true;
return;
}
int ans=;
void search(int c)
{
int e=,d=c-;
while(d>=&&a[e].z[s[d]-])
{
//cout<<c<<" ";
e=a[e].z[s[d]-];
if(a[e].en)
{
if(f[d]||d==)
{f[c]=;ans=c;return;}
}
d--;
}
return;
}
int main()
{
//freopen("a.in","r",stdin);
int n,m;
cin>>n>>m;
for(int i=;i<=n;++i)
{
cin>>s;
build();
}
for(int i=;i<=m;++i)
{
ans=;
cin>>s;
int len=strlen(s);
memset(f,,sizeof(f));
f[]=;
for(int j=;j<=len;++j)
search(j);
cout<<ans<<endl;
}
return ;
}

感觉自己现在写不出这种上古绝学了QAQ(逃

用AC自动机把单词出现的位置跑出来,转换成区间

问题转换成选择不重合的区间从0开始覆盖,最远的覆盖到哪儿。

然后写一个BFS跑一下就行了。

BFS:首先把0push进队列,然后跑以0为左端点的区间,每次把右端点push进去。

加上判重之后可以$O(L)$。

居然比上古绝学慢了三百毫秒QAQ

 /*
qwerta
P2292 [HNOI2004]L语言
Accepted
100
代码 C++,2.53KB
提交时间 2018-10-08 08:42:03
耗时/内存
1121ms, 28908KB
*/
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<cmath>
using namespace std;
#define R register
struct emm{
int fal;
int nxt[];
int tag,l;
}AC[];//Tree结构体
queue<int>q;
struct ahh{
int f,e;
}a[];//用来区间覆盖
int h[];
bool sf[];//判重
int main()
{
//freopen("a.in","r",stdin);
ios::sync_with_stdio(false);
cin.tie(false),cout.tie(false);//关闭同步流(卡常
int n,m;
cin>>n>>m;
int cnt=;
//build_Trie
for(R int i=;i<=n;++i)
{
string s;
cin>>s;
int len=s.length();
int now=;
for(R int j=;j<len;++j)
{
if(!AC[now].nxt[s[j]-'a'])
AC[now].nxt[s[j]-'a']=++cnt;
now=AC[now].nxt[s[j]-'a'];
}
AC[now].tag=i;
AC[now].l=len;//记录这个区间的长度
}
//get_fail
{
for(R int i=;i<;++i)
if(AC[].nxt[i])
{
AC[AC[].nxt[i]].fal=;
q.push(AC[].nxt[i]);
}
while(!q.empty())
{
int x=q.front();q.pop();
for(R int i=;i<;++i)
{
if(AC[x].nxt[i])
{
AC[AC[x].nxt[i]].fal=AC[AC[x].fal].nxt[i];
q.push(AC[x].nxt[i]);
}
else
AC[x].nxt[i]=AC[AC[x].fal].nxt[i];
}
}
}
//runAC
for(R int i=;i<=m;++i)
{
//cout<<"i="<<i<<endl;
memset(a,,sizeof(a));
memset(h,,sizeof(h));
int tot=;
string t;
cin>>t;
int lent=t.length();
int now=;
for(R int j=;j<lent;++j)
{
now=AC[now].nxt[t[j]-'a'];
for(R int k=now;k;k=AC[k].fal)
if(AC[k].tag)
{
//a[++tot].r=j;
//a[tot].l=j-AC[k].l+1;
int ll=j-AC[k].l+;//这个区间的左端点=右端点-长度+1
a[++tot].f=h[ll];//邻接链表加边
h[ll]=tot;
a[tot].e=j;
}
}
//cout<<"get"<<endl;
//bfs
memset(sf,,sizeof(sf));
int ans=-;
{
q.push();
while(!q.empty())
{
int x=q.front();q.pop();
//cout<<"x="<<x<<endl;
ans=max(ans,x-);
for(R int i=h[x];i;i=a[i].f)
if(!sf[a[i].e])//判重
{
sf[a[i].e]=;
q.push(a[i].e+);
//cout<<"push "<<a[i].e+1<<endl;
}
}
}
cout<<ans+<<endl;
}
return ;
}

「HNOI2004」「LuoguP2292」L语言(AC自动机的更多相关文章

  1. BZOJ 1212: [HNOI2004]L语言 [AC自动机 DP]

    1212: [HNOI2004]L语言 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1367  Solved: 598[Submit][Status ...

  2. 【bzoj1212】[HNOI2004]L语言 AC自动机

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

  3. bzoj 1212: [HNOI2004]L语言 AC自动机+状压

    为什么这道题网上所有题解写的都是N*Len的trie树的暴力啊,4E的复杂度... 为什么暴力还跑这么快啊TAT.. 有一个O(Len)的做法就是先把AC自动机建出来,因为每个字典串的长度很小,所以我 ...

  4. [HNOI2004] L语言 - AC自动机,dp

    给定字典和没有标点的文章,求能够被识别的最长前缀. 显然不能贪心,设\(f[i]\)表示前\(i\)个字符构成的前缀能否被识别,然后在AC自动机上暴力转移即可. 具体来说,每走到一个新位置,就沿着fa ...

  5. 「模拟赛20180306」回忆树 memory LCA+KMP+AC自动机+树状数组

    题目描述 回忆树是一棵树,树边上有小写字母. 一次回忆是这样的:你想起过往,触及心底--唔,不对,我们要说题目. 这题中我们认为回忆是这样的:给定 \(2\) 个点 \(u,v\) (\(u\) 可能 ...

  6. [bzoj1212][HNOI2004]L语言_AC自动机_动态规划

    L语言 bzoj-1212 HNOI-2004 题目大意:给你一个n个单词的集合,然后给你m条字符串.问每条字符串可以被理解的最长前缀.被理解当且仅当存在一种分割使得每一段都是集合里的元素. 注释:$ ...

  7. 【HNOI2004】【P1365】L语言

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

  8. 「USACO08DEC」「LuoguP2922」秘密消息Secret Message(AC自动机

    题目描述 Bessie is leading the cows in an attempt to escape! To do this, the cows are sending secret bin ...

  9. BZOJ 1212 HNOI2004 L语言 AC自己主动机(Trie树)+动态规划

    标题效果:给定词的列表,并m串 每个字符串q个最长前缀,这个前缀可满足拆分成一些字符串 这些字符串中存在的词汇太 再也不怕错误的数据范围--有一个很明显Trie树能解决的问题竟然被我写的AC自己主动机 ...

随机推荐

  1. NFC模组,开发NFC功能 仅仅要几条指令的事情

    特点:实现NFC透明传输.内置NFC协议栈,支持UART串口直接读写,用于门禁能够同一时候兼容手机和卡片开门,还能实现动态密钥,读到的NFC数据自己主动串口输出,会串口就能开发NFC,不须要研究LLC ...

  2. 赵雅智_Fragment

    当我们须要动态的多界面切换的时候,就须要将UI元素和Activity融合成一个模块. 在2.3中我们一般通过各种Activity中进行跳转来实现多界面的跳转和单个界面动态改变.在4.0或以上系统中就能 ...

  3. OS: 读者写者问题(写者优先+LINUX+多线程+互斥量+代码)(转)

    一. 引子 最近想自己写个简单的 WEB SERVER ,为了先练练手,熟悉下在LINUX系统使用基本的进程.线程.互斥等,就拿以前学过的 OS 问题开开刀啦.记得当年学读者写者问题,尤其是写者优先的 ...

  4. Codeforces Round #267 (Div. 2) B. Fedor and New Game

    After you had helped George and Alex to move in the dorm, they went to help their friend Fedor play ...

  5. cvpr2017-code-etc

    cvpr2017: code:   http://staffhome.ecm.uwa.edu.au/~00053650/code.html

  6. bootstrap table api

    http://blog.csdn.net/rickiyeat/article/details/56483577

  7. 安装protobuf可能遇到的问题

    下载protobuf-2.3.0:    http://protobuf.googlecode.com/files/protobuf-2.3.0.zip http://code.google.com/ ...

  8. 使用Apache Commons Chain(转载)

    原博客出处:http://phil-xzh.iteye.com/blog/321536 使用Commons Chain 作为程序开发人员,我们经常需要对一个实际上程序性的系统应用面向对象的方法.商业分 ...

  9. “ 不确定 "限制值的使用

    前言 前篇文章解释了限制值的五种类型以及获取它们的方法.但是对于其中可能不确定的类型( 45类型 ),当限制值获取函数返回-1的时候,我们无法仅通过这个函数返回值-1来判断是限制值获取失败还是限制值是 ...

  10. Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit)

    Error: Package: mysql-community-server-8.0.12-1.el7.x86_64 (mysql80-community) Requires: libstdc++.s ...