洛谷 P2292 [HNOI2004]【L语言】

题目描述

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

一段文章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  (没有任何前缀能够被理解)

解题思路

  这道题是典型的字典树。我们先从头预处理可查到的单词,然后标记单词结尾的节点的编号,再向后查找,是否在字典里,这样一直下去即可。

题解

 1 #include<bits/stdc++.h>
 2 #define N 1000010
 3 using namespace std; 
 4 int n,m;
 5 bool flag[N];//标记字符串中单词结尾的 
 6 struct Trie{
 7     int sz;
 8     int ch[N][26];
 9     int val[N];
10     Trie(){
11         sz=1;
12         memset(ch[0],0,sizeof(ch[0]));
13     }//初始化 
14     int idx(char c)
15     {
16         return c-'a';
17     }
18     void insert(string s)
19     {
20         int u=0;
21         for(int i=0;i<s.size();i++)
22         {
23             int c=idx(s[i]);
24             if(!ch[u][c])
25             {
26                 memset(ch[sz],0,sizeof(ch[sz]));
27                 ch[u][c]=sz;
28                 sz++;
29             }
30             u=ch[u][c];
31         }
32         val[u]=1;//给单词结尾打上标记 
33     }
34     void find(string s)
35     {
36         int u=0,ans=0;
37         memset(flag,0,sizeof(flag));//记得初始化 
38         for(int i=0;i<s.size();i++)
39         {
40             int c=idx(s[i]);
41             if(!ch[u][c])break; 
42             u=ch[u][c];
43             if(val[u]==1)flag[i]=1;
44         } 
45         for(int i=0;i<s.size();i++)
46         {
47             if(!flag[i])continue;//我们只找结尾的 
48             else ans=i+1;
49             u=0;
50             for(int j=i+1;j<s.size();j++)
51             {
52                 int c=idx(s[j]);
53                 if(!ch[u][c])break;
54                 u=ch[u][c];
55                 if(val[u]==1)flag[j]=1;//结尾 
56             }
57         }
58         printf("%d
",ans);
59     }
60 }tree; 
61 int main()
62 {
63     cin>>n>>m;
64     string a;
65     for(int i=1;i<=n;i++)
66     {
67         cin>>a;
68         tree.insert(a);//插入 
69     }
70     for(int i=1;i<=m;i++)
71     {
72         cin>>a;
73         tree.find(a);//查找 
74     }
75     return 0;
76 }
原文地址:https://www.cnblogs.com/hualian/p/11200783.html