UVAlive 5792 Diccionário Portuñol (Trie)
来源:互联网 发布:乐器模拟软件排行 编辑:程序博客网 时间:2024/05/02 00:41
转载请注明出处,谢谢http://blog.csdn.net/ACM_cxlove?viewmode=contents by---cxlove
题目:有两个字符串集合,从第一个集合中取某个串的非空前缀,从第二个集合中取某个串的非空后缀,拼接成一个串,问有多少个不同的新串。
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=3803
大概是N年前训练的题。。。然后不会做,就没管了
最近波波好同学问了御坂姐姐,然后就会做了,其实很水。。。
为何这么弱。。。。
首先把第一个集合中的串加入到Trie中,然后就可以枚举前缀了,然后就是统计后缀,麻烦的是可能出现重复的。
当我们按长度枚举前缀的时候,可以考虑如果后缀的前缀出现在前缀的后继中,那便不用考虑,后面总会统计到。
这样的话,其实只要比较第一个字母。
如果当前结点P表示一个前缀串,那么如果p -> next[i]为空,说明前缀中不含字母i为后继,那么我们就可以统计以i开头的后缀了。否则总能在p -> next[i]为前缀中统计到。
有一点需要注意的是,如果 p -> next[i]便是我们最终的串,即以p 为前缀时,后缀只有一个字母的话,那就不能把这一个字母拉入到前缀中,因为后缀是非空的。所以再处理下end[i],表示是否存在以单个字母i为后缀的。
至于统计以i开头的不重复后缀的话,可以反向加入到Trie中统计。
#include <iostream>#include <cstdio>#include <algorithm>#include <vector>#include <cstring>using namespace std;typedef long long LL;const int M = 100005;const int N = 1005;int n , m , cnt[26] , end[26];char a[N][N] , b[N][N];LL ans = 0;struct Trie { int tot; struct trie { trie *next[26]; }s[M] , *root; trie *newnode () { trie *p = &s[tot ++]; memset (p -> next , 0 , sizeof(p -> next)); return p; } void init () { memset (cnt , 0 , sizeof(cnt)); tot = 0; root = newnode (); } void insert (char *s) { trie *p = root; for (int i = 0 ; s[i] ; i ++) { int c = s[i] - 'a'; if (p -> next[c] == NULL) { p -> next[c] = newnode (); } p = p -> next[c]; } } void cal (trie *p) { for (int i = 0 ; i < 26 ; i ++) { if (p -> next[i]) { cnt[i] ++; cal (p -> next[i]); } } } void gao (trie *p) { for (int i = 0 ; i < 26 ; i ++) { if (p -> next[i] == NULL) { if (p != root) ans += cnt[i]; } else { if (p != root && end[i]) ans ++; gao (p -> next[i]); } } }}suffix , prefix;int main () { while (scanf ("%d %d" , &n , &m) != EOF && n + m) { prefix.init ();suffix.init (); ans = 0; memset (cnt , 0 , sizeof (cnt)); memset (end , 0 , sizeof (end)); for (int i = 0 ; i < n ; i ++) { scanf ("%s" , a[i]); prefix.insert (a[i]); } for (int i = 0 ; i < m ; i ++) { scanf ("%s" , b[i]); reverse (b[i] , b[i] + strlen(b[i])); end[b[i][0] - 'a'] = 1; suffix.insert (b[i]); } suffix.cal (suffix.root); prefix.gao (prefix.root); printf ("%lld\n" , ans); } return 0;}
- UVAlive 5792 Diccionário Portuñol (Trie)
- UVAlive - 5792 Diccionário Portuñol (Trie)
- UVALive 5792 Diccionário Portuñol(字典树)
- UVAlive5792 Diccionário Portuñol
- BNU 12674 Diccionário Portuñol (字典树统计)
- UVALIVE 5792 Trie+统计
- rio
- uvalive 3942(dp + trie)
- uvalive 7043(trie)
- UVALive 3942 Trie加速dp
- UVALive 5913 Dictionary Size (Trie)
- ol
- ol
- UVALive - 3942 Remember the Word (Trie)
- UVALive (LA) - 3942 UVa 1401 Trie
- uvalive 3942 - Remember the Word(Trie)
- Cellphone Typing - UVaLive 6133 Trie树
- UVALive - 3942 Remember the Word Trie
- Linux共享内存编程实例
- linux c学习 day03
- iOS开发之数组排序(数组中包括字典)
- Android资源——布局资源
- 简单理解transaction
- UVAlive 5792 Diccionário Portuñol (Trie)
- PID control model----PID controlor
- 开源svn地址
- 简直不能忍!org.xmlpull.v1.XmlPullParserException: expected: START_TAG 处理心得
- 何时才是个头
- 最大子段和问题小结
- Ubuntu 截图
- RTSP协议学习笔记
- Linux旗语编程实例