• hdu 1403 Longest Common Substring


    我是不是真的需要学学后缀数组了,这个题我是用后缀自动机写出来的。写的比较辛苦吧,不过对后缀自动机的理解又进了一步。不废话了,题意是让你求两个字符串的最长公共子串的长度。

    现在贴上我的代码:

    View Code
    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <queue>
    
    #include <map>
    
    using namespace std;
    
    const int maxlen=100000+5;
    
    char s1[maxlen],s2[maxlen];
    int cnt;
    
    struct node
    {
        int len;
        node *next[26];
        node *fail;
    }memory[1000000];
    
    node *createnode(int l,node *fail)
    {
        node *p=&memory[cnt];
        memory[cnt].len=l;
        memory[cnt].fail=fail;
        memset(memory[cnt++].next,NULL,sizeof(node *)*26);
        return p;
    }
    
    class SAM
    {
        public:
        node *root;
        SAM()
        {
            root=NULL;
        }
        void Insert(char *str)
        {
            if(!root)
                root=createnode(0,NULL);
            node *loca=root;
            for(int i=0;str[i];i++)
            {
                int num=str[i]-'a';
                if(loca->next[num]==NULL)
                    loca->next[num]=createnode(i+1,NULL);
                loca=loca->next[num];
            }
        }
        void Build()
        {
            std::queue<node *>s;
            while(!s.empty())
                s.pop();
            s.push(root);
            while(!s.empty())
            {
                node *loca=s.front();
                s.pop();
                for(int i=0;i<26;i++)
                {
                    if(loca->next[i]!=NULL)
                    {
                        if(loca==root)
                            loca->next[i]->fail=root;
                        else
                        {
                            node *tmp=loca->fail;
                            while(tmp!=NULL)
                            {
                                if(tmp->next[i]!=NULL)
                                    break;
                                tmp->next[i]=loca->next[i];
                                tmp=tmp->fail;
                            }
                            if(tmp==NULL)
                                loca->next[i]->fail=root;
                            else if(tmp->next[i]->len==tmp->len+1)
                                loca->next[i]->fail=tmp->next[i];
                            else
                            {
                                node *t=tmp->next[i];
                                node *nt=createnode(tmp->len+1,t->fail);
                                t->fail=loca->next[i]->fail=nt;
                                memcpy(nt->next,t->next,sizeof(node *)*26);
                                while(tmp&&tmp->next[i]==t)
                                {
                                    tmp->next[i]=nt;
                                    tmp=tmp->fail;
                                }
                            }
                        }
                        s.push(loca->next[i]);
                    }
                }
            }
        }
        int maxCommonLen(char *s1,char *s2)
        {
            node *loca=root;
            int ans,len;
            ans=len=0;
            for(int i=0;s2[i];i++)
            {
                int num=s2[i]-'a';
                if(loca->next[num])
                {
                    len++;
                    loca=loca->next[num];
                }
                else
                {
                    node *tmp=loca->fail;
                    while(tmp&&!tmp->next[num])
                        tmp=tmp->fail;
                    if(tmp)
                    {
                        len=tmp->len+1;
                        loca=tmp->next[num];
                    }
                    else
                    {
                        loca=root;
                        len=0;
                    }
                }
                ans=(ans<len)?len:ans;
            }
            return ans;
        }
    };
    
    
    
    
    int main()
    {
        while(~scanf("%s %s",s1,s2))
        {
            SAM sam;
            cnt=0;
            sam.Insert(s1);
            sam.Build();
            printf("%d\n",sam.maxCommonLen(s1,s2));
        }
        return 0;
    }

    之前自己曾在百度知道上面问了个问题,内容是,字符串的处理,我该怎么来学,前提我当时学会了kmp和字典树,回答是让我把ac自动机跟后缀数组再学一下。我真的需要学习一下后缀数组嘛?说实话我对后缀数组思路里面的那几个数组实在是不怎么感冒。所以就直接绕来学后缀自动机了。请大牛为我指条明路!

  • 相关阅读:
    「ZJOI2019」开关 (概率期望+FWT)
    FJWC2020 Day3 题解
    FJWC2020 Day1 题解
    「ZJOI2019」Minimax 搜索(动态dp)
    「十二省联考 2019」希望(长链剖分优化dp)
    CF1097F Alex and a TV Show(莫比乌斯反演+bitset)
    [Luogu#4707] 重返现世(minmax容斥+背包dp)
    201871010105曹玉中《面向对象程序设计(java)》第十周学习总结 曹玉中
    201871010105曹玉中《面向对象程序设计(Java)》第一周学习总结 曹玉中
    201871010105曹玉中《面向对象程序设计(java)》第四周学习总结 曹玉中
  • 原文地址:https://www.cnblogs.com/RainingDays/p/2792669.html
Copyright © 2020-2023  润新知