Corporate Identity - HDU 2328(多串求共同子串)
2015-08-19 09:29
302 查看
题目大意:给你N(2-4000)个字符串,求出来他们的共同子串
分析:因为上次就说了再出现这种题就不用那种暴力的做法了,于是看了一些别的知识,也就是后缀树,把一个字符串的所有的后缀全部都加入字典树,然后用别的串去匹配,这样匹配的时候速度那是飕飕的啊,不过第一次我把前N-1个串的所有前缀搞进了字典树里面,然后想如果某个节点被访问N-1次,并且第N个串也能访问到此节点,那么这一定就是他们的共同子串了,不过总归是太天真,直接返回MLE,一细琢磨,想着最糟糕的情况也就是有8000(N)个串,每个串都不相同,并且每个串的长度是200(len),那么空间复杂度应该是 len*(len+1)/2*N*26 大约理论上最糟糕的情况就是41亿内存,不超才见鬼了呢于是又换一种想法,如果只把第一个串的所有后缀加入字典树不就行了?因为求的是共同子串,第一个串也肯定包括所有串的共同子串,这样内存开销就会降到len*(len+1)/2*26大约50w不到,比较容易接受了。
下面是AC代码:
==========================================================================================================
分析:因为上次就说了再出现这种题就不用那种暴力的做法了,于是看了一些别的知识,也就是后缀树,把一个字符串的所有的后缀全部都加入字典树,然后用别的串去匹配,这样匹配的时候速度那是飕飕的啊,不过第一次我把前N-1个串的所有前缀搞进了字典树里面,然后想如果某个节点被访问N-1次,并且第N个串也能访问到此节点,那么这一定就是他们的共同子串了,不过总归是太天真,直接返回MLE,一细琢磨,想着最糟糕的情况也就是有8000(N)个串,每个串都不相同,并且每个串的长度是200(len),那么空间复杂度应该是 len*(len+1)/2*N*26 大约理论上最糟糕的情况就是41亿内存,不超才见鬼了呢于是又换一种想法,如果只把第一个串的所有后缀加入字典树不就行了?因为求的是共同子串,第一个串也肯定包括所有串的共同子串,这样内存开销就会降到len*(len+1)/2*26大约50w不到,比较容易接受了。
下面是AC代码:
==========================================================================================================
#include<stdio.h> #include<string.h> #include<algorithm> #include<stdlib.h> using namespace std; const int MAXN = 26; const int MAXM = 1007; const int oo = 1e9+7; struct node { int times; node *next[MAXN]; }; int BuildTrie(node *head, char s[], int x) { int i, k, depth = 0; node *P = head; for(i=0; s[i]; i++) { k = s[i] - 'a'; if(P->next[k] == NULL) { if(x != 1) break; P->next[k] = new node(); } P = P->next[k]; if(P->times + 1 >= x) {///如果此节点是本个串访问过或者上个节点访问过 P->times = x; depth++; } else break; } return depth; } void clearTrie(node *head) {///销毁树 node *P = head; for(int i=0; i<MAXN; i++) { if(P->next[i] != NULL) clearTrie(P->next[i]); } free(P); } int main() { int i, j, N; while(scanf("%d", &N), N) { node *head = new node(); char s[MAXM]={0}, ans[MAXM]={0}; for(i=1; i<N; i++) { scanf("%s", s); for(j=0; s[j] != '\0'; j++) BuildTrie(head, s+j, i); } scanf("%s", s); int Max = 0; for(j=0; s[j] != '\0'; j++) { int len = BuildTrie(head, s+j, N); char p[MAXM] = {0}; strncpy(p, s+j, len); if(Max < len || (Max==len && strcmp(ans, p) > 0)) strcpy(ans, p), Max = len; } if(ans[0] == 0) printf("IDENTITY LOST\n"); else printf("%s\n", ans); clearTrie(head); } return 0; }
相关文章推荐
- Toolbar的各种使用方法
- 根据与目标距离排序
- 动态规划_拦截导弹
- OverFeat Integrated Recognition, Localization and Detection using Convolutional Networks
- android 源码在线
- Hadoop导航:版本、生态圈及MapReduce模型
- C#精髓 第四讲 GridView 72般绝技
- MAVEN环境变量配置
- hdu4419 Colourful Rectangle(离散,线段树,线扫描,状压)
- ALBB 找公共最长连续字母序列的长度
- java中计算两个时间差
- 关于从一个Fragment跳转到一个Activity中
- 动态规划_拦截导弹
- 时间戳
- 【C#】窗体动画效果
- win7下通过easyBCD引导安装Ubuntu14.04
- 非常难得的iPad版房地产售楼助手应用源码项目
- 线程同步与互斥:读写锁
- 第9章 Servlet的配置与使用
- C#多态性详解