码迷,mamicode.com
首页 > 其他好文 > 详细

Corporate Identity - HDU 2328(多串求共同子串)

时间:2015-08-19 10:40:24      阅读:140      评论:0      收藏:0      [点我收藏+]

标签:

题目大意:给你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代码:
==========================================================================================================
#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;
}

 

Corporate Identity - HDU 2328(多串求共同子串)

标签:

原文地址:http://www.cnblogs.com/liuxin13/p/4741283.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!