UvaLive 4670 Dominating Patterns

二次联通门 : UvaLive 4670 Dominating Patterns

 

 

 

/*
    UvaLive 4670 Dominating Patterns 

    AC自动机
    
    题目大意
    有个由小写字母组成的模式串以及一个文本串。
    每个模式串可能会在文本串中出现多次。
    你需要找出哪些模式串在文本串中出现的次数最多。 
    
    注意可能会有多组相同的模式串
    
    加个数组判一判就好了。。
    
    具体是在Trie树中的叶节点维护一个small_number
    表示最早的串
    
    之后计数什么的, 都记到这个上 
*/
#include <cstring>
#include <cstdio>
#include <queue>

#define Max 1000009

bool read (int &now)
{
    now = 0;
    register char word = getchar ();
    while (word < '0' || word > '9')
        word = getchar ();
    while (word >= '0' && word <= '9')
    {
        now = now * 10 + word - '0';
        word = getchar ();
    }
    return now > 0;
}

inline int max (int a, int b)
{
    return a > b ? a : b;
}

struct Trie_Data
{

    Trie_Data *Fail;
    Trie_Data *child[26];
    
    int small_number;
    Trie_Data ()
    {
        for (int i = 0; i < 26; i ++)
            this->child[i] = NULL;
            
        this->Fail = NULL;
        small_number = 0;
    }    
};

Trie_Data *Root;

int number[Max / 1000];
int count[Max / 1000];

char line[Max / 1000][Max / 1000];
char Need[Max];

int Answer;

class AC_Type
{
    private :
        
        int __Count_;

    public :
    
        void Clear ()
        {
            __Count_ = 0;
            memset (number, 0, sizeof (number));
            memset (count, 0, sizeof count);
        }
        
        void Insert (char *key)
        {
            int Len = strlen (key);
            __Count_ ++;
            
            Trie_Data *now = Root, *pos;
            int Id;
            
            for (int i = 0; i < Len; i ++)
            {
                Id = key[i] - 'a';
                if (now->child[Id] == NULL)
                    now->child[Id] = new Trie_Data;
                now = now->child[Id];
            }
            if (!now->small_number)
                now->small_number = __Count_;
            number[__Count_] = now->small_number;
        }
        
        void Build_AC ()
        {
            std :: queue <Trie_Data *> Queue;
            
            Queue.push (Root);  
            Trie_Data *now, *pos;
            while (!Queue.empty ())
            {
                pos = NULL;
                now = Queue.front ();
                Queue.pop ();
                
                for (int i = 0; i < 26; i ++)
                {
                    if (now->child[i] == NULL)
                        continue;
                    if (now == Root)
                        now->child[i]->Fail = Root;
                    else
                    {
                        for (pos = now->Fail; pos; pos = pos->Fail)
                            if (pos->child[i])
                            {
                                now->child[i]->Fail = pos->child[i];
                                break;
                            }
                        if (pos == NULL)
                            now->child[i]->Fail = Root;
                    }
                    Queue.push (now->child[i]); 
                }  
            }
        }
        
        void Query (char *key)
        {
            Trie_Data *now = Root, *pos;
            
            int Len = strlen (key);
            int Id;
            
            for (int i = 0; i < Len; i ++)
            {
                Id = key[i] - 'a';
                for (; now != Root && now->child[Id] == NULL; now = now->Fail);
                
                now = now->child[Id];
                if (now == NULL)
                    now = Root;
                for (pos = now; pos != Root; pos = pos->Fail)
                    count[pos->small_number] ++;
            }
        }
};

AC_Type Make;

int main (int argc, char *argv[])
{
    int N;
    for (int N; read (N); )
    {
        Root = new Trie_Data;
        Make.Clear ();
        for (register int i = 1; i <= N; i ++)
        {
            scanf ("%s", line[i]);
            Make.Insert (line[i]); 
        }
        Make.Build_AC ();
        scanf ("%s", Need);
        Make.Query (Need);
        Answer = 0;
        for (int i = 1; i <= N; i ++)
            Answer = max (Answer, count[i]);
        printf ("%d\n", Answer);
        for (int i = 1; i <= N; i ++)
            if (count[number[i]] == Answer)
                puts (line[i]);
    }    
    return 0;
}

 

posted @ 2017-06-10 18:04  ZlycerQan  阅读(282)  评论(0编辑  收藏  举报