BZOJ1212: [HNOI2004]L语言(Trie图+DP)
Description
标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的。现在你要处理的就是一段没有标点的文章。 一段文章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下能够被理解的最长前缀的位置。
Input
输入文件第一行是两个正整数n和m,表示字典D中有n个单词,且有m段文章需要被处理。 之后的n行每行描述一个单词,再之后的m行每行描述一段文章。 其中1<=n, m<=20,每个单词长度不超过10,每段文章长度不超过1M。
Output
对于输入的每一段文章,你需要输出这段文章在字典D可以被理解的最长前缀的位置。
Sample Input
is
name
what
your
whatisyourname
whatisyouname
whaisyourname
Sample Output
6
0
解题思路:
最长可理解前缀,可以认为是在Trie图匹配时维护一个bool型数组
记录匹配成功的单词,若此单词独立,就更新dp数组
代码:
#include<queue>
#include<cstdio>
#include<cstring>
#include<algorithm>
using std::max;
struct trnt{
int ch[];
int fl;
int fin;
}tr[];
char tmp[];
int ln[];
bool dp[];
int siz;
int n,m;
std::queue<int>Q;
void Insert(char *a,int k,int &len)
{
len=strlen(a+);
int root=;
for(int i=;i<=len;i++)
{
int c=a[i]-'a';
if(!tr[root].ch[c])
tr[root].ch[c]=++siz;
root=tr[root].ch[c];
}
tr[root].fin=k;
return ;
}
void Build()
{
int root=;
for(int i=;i<;i++)
if(tr[root].ch[i])
Q.push(tr[root].ch[i]);
while(!Q.empty())
{
root=Q.front();
Q.pop();
for(int i=;i<;i++)
{
if(tr[root].ch[i])
{
tr[tr[root].ch[i]].fl=tr[tr[root].fl].ch[i];
Q.push(tr[root].ch[i]);
}else
tr[root].ch[i]=tr[tr[root].fl].ch[i];
}
}
return ;
}
int Dp(char *a)
{
int len=strlen(a+);
for(int i=;i<=len;i++)
dp[i]=;
dp[]=;
int ans=;
int root=;
for(int i=;i<=len;i++)
{
int c=a[i]-'a';
root=tr[root].ch[c];
for(int j=root;j;j=tr[j].fl)
if(tr[j].fin&&dp[i-ln[tr[j].fin]])
{
dp[i]=true;
ans=max(ans,i);
break;
}
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++)
{
scanf("%s",tmp+);
Insert(tmp,i,ln[i]);
}
Build();
while(m--)
{
scanf("%s",tmp+);
printf("%d\n",Dp(tmp));
}
return ;
}
BZOJ1212: [HNOI2004]L语言(Trie图+DP)的更多相关文章
- BZOJ1212[HNOI2004]L语言——trie树+DP
题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构成.一个单词W也是由若干小写字母构成.一个字典D是若干个单词的 ...
- 【BZOJ1212】[HNOI2004]L语言 Trie树
[BZOJ1212][HNOI2004]L语言 Description 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构 ...
- Luogu P2292 [HNOI2004]L语言(Trie+dp)
P2292 [HNOI2004]L语言 题面 题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章 \(T\) 是由若干小写字母构成. ...
- BZOJ 1212: [HNOI2004]L语言 [AC自动机 DP]
1212: [HNOI2004]L语言 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1367 Solved: 598[Submit][Status ...
- bzoj1212: [HNOI2004]L语言(字典树)
1212: [HNOI2004]L语言 题目:传送门 题解: 看完题目之后就觉得可以暴力在字典树上之间询问,一开始还傻了以为用文章来建,肯定用单词啊: 那么我们可以用一个v数组表示当前字符串1~i的区 ...
- 洛谷.2292.[HNOI2004]L语言(Trie DP)
题目链接 /* 简单的DP,查找是否有字典中的单词时在Trie树上做 要注意在最初Match(0)一遍后,i还是要从0开始匹配,因为如果有长度为1的单词,Match(i+1)不会从1更新 1M=102 ...
- [bzoj1212][HNOI2004]L语言_AC自动机_动态规划
L语言 bzoj-1212 HNOI-2004 题目大意:给你一个n个单词的集合,然后给你m条字符串.问每条字符串可以被理解的最长前缀.被理解当且仅当存在一种分割使得每一段都是集合里的元素. 注释:$ ...
- 【Trie】bzoj1212 [HNOI2004]L语言
枚举每个文章里已经在Trie中被标记为可能是分割处的字符,然后再从此处跑Trie,继续向后标记.由于单词数很少,因此复杂度可以接受,O(n*m*Len). #include<cstdio> ...
- [HNOI2004]L语言 trie树? Ac自动机? hash!!
题目描述 标点符号的出现晚于文字的出现,所以以前的语言都是没有标点的.现在你要处理的就是一段没有标点的文章. 一段文章T是由若干小写字母构成.一个单词W也是由若干小写字母构成.一个字典D是若干个单词的 ...
随机推荐
- POJ 1258 Agri-Net (最小生成树+Prim)
Agri-Net Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 39820 Accepted: 16192 Descri ...
- OpenCV学习笔记09--通过cvPtr2D或指针算法绘制图形
练习:创建一个1000*1000的三通道图像,将其元素所有置0.以(200,50)和(400,200)为顶点绘制一个绿色平面 我们能够用两种方法来实现这一功能,一个是使用cvPtr2D,可是因为使用了 ...
- hdu 3068 最长回文 【Manacher求最长回文子串,模板题】
欢迎关注__Xiong的博客: http://blog.csdn.net/acmore_xiong?viewmode=list 最长回文 ...
- Unity multiplayer
using UnityEngine; using System.Collections; public class multiplayer_Button : MonoBehaviour { void ...
- BZOJ 1306 DFS
思路: 搜索就好 (注意不要枚举太多东西) //By SiriusRen #include <cstdio> using namespace std; int n,point[10],an ...
- BZOJ 1103 DFS序+线段树
思路: 先搞出来DFS序 进入这个点 +1 出这个点 -1 线段树维护前缀和 (因为还要修改) 搞定 修改的时候只修改底下节点就OK了 (边权–>点权 不多说) //By SiriusRen # ...
- 洛谷T21776 子序列
题目描述 你有一个长度为 nn 的数列 \{a_n\}{an} ,这个数列由 0,10,1 组成,进行 mm 个的操作: 1~l~r1 l r :把数列区间 [l, r][l,r] 内的所有数取反. ...
- Django_shell命令操作
- caioj 1065 动态规划入门(一维一边推3:合唱队形)
就是最长上升子序列,但是要用n^2的算法. #include<cstdio> #include<algorithm> #define REP(i, a, b) for(int ...
- Android布局之RelativeLayout
RelativeLayout用到的一些重要的属性: 第一类:属性值为true或falseandroid:layout_centerHrizontal 水平居中android:layout_center ...