• 刷题总结——spoj1812(后缀自动机+DP)


    题目:

    A string is finite sequence of characters over a non-empty finite set Σ.

    In this problem, Σ is the set of lowercase letters.

    Substring, also called factor, is a consecutive sequence of characters occurrences at least once in a string.

    Now your task is simple, for two given strings, find the length of the longest common substring of them.

    Here common substring means a substring of two or more strings.

    Input

    The input contains exactly two lines, each line consists of no more than 250000 lowercase letters, representing a string.

    Output

    The length of the longest common substring. If such string doesn't exist, print "0" instead.

    Example

    Input:
    alsdfkjfjkdsal
    fdjskalajfkdsla
    
    Output:
    3
    

    Notice: new testcases added

     Submit solution!

    题解:

    注:参照神犇hahalidaxin的题解.

    SAM+DP

    先拿个串建个SAM,然后用后面的串匹配,每次将所有的匹配长度记录在状态上取min,然后对所有状态取max即答案。

    需要更新fa,因为fa[p]一定比p更优,但匹配的时候可能只更新了p而没有更新fa[p],所以还需要递推一边。

    注意mn[p]初始化为l[p]

    心得:

    目前没什么好说的··dp和sam都不熟的情况下想做这道题真的很懵b····感觉没什么收获··以后再来看看吧···

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    using namespace std;
    const int N=250005;
    int pre[N],son[N][26],step[N],last=1,root=1,tot=1,minn[N],maxx[N];
    int cnt[N],len,b[N];
    char s[N];
    struct suffix_auto
    {
      void extend(int ch)
      {
        int p=last,np=++tot;
        minn[tot]=step[tot]=step[last]+1;
        for(;p&&!son[p][ch];p=pre[p])  son[p][ch]=np;
        if(!p)  pre[np]=root;
        else
        {
          int q=son[p][ch];
          if(step[q]!=step[p]+1)
          {
            int nq=++tot;  
            minn[nq]=step[nq]=step[p]+1;
            memcpy(son[nq],son[q],sizeof(son[q]));
            pre[nq]=pre[q];
            pre[q]=pre[np]=nq;
            for(;son[p][ch]==q;p=pre[p])  son[p][ch]=nq;
          }
          else
            pre[np]=q;    
        }
        last=np;
      }
      void build()
      {
        scanf("%s",s);
        len=strlen(s);
        for(int i=0;i<len;i++)
          extend(s[i]-'a');
      }
    }automa;
    int main()
    {
      freopen("a.in","r",stdin);
      automa.build();
      for(int i=1;i<=tot;i++)  cnt[step[i]]++;
      for(int i=1;i<=len;i++)  cnt[i]+=cnt[i-1];
      for(int i=1;i<=tot;i++)  b[cnt[step[i]]--]=i;
      while(scanf("%s",s)==1)
      {
        int len1=strlen(s);  
        int p=root,len=0;
        for(int i=0;i<len1;i++)
        {
          int ch=s[i]-'a';
          if(son[p][ch])  len++,p=son[p][ch];
          else
          {
            while(p&&!son[p][ch])  p=pre[p];
            if(!p)  len=0,p=root;
            else
            {
              len=step[p]+1;
              p=son[p][ch];
            }
          }
          if(maxx[p]<len)  maxx[p]=len;
        }
        for(int i=tot;i;i--)  
        { 
          int j=b[i];
          if(maxx[j]<minn[j])  minn[j]=maxx[j];
          if(pre[p]&&maxx[pre[j]]<maxx[j])  maxx[pre[j]]=maxx[j];
          maxx[j]=0;
        }
      }
      int ans=0;
      for(int i=1;i<=tot;i++)
        ans=max(ans,minn[i]);
      cout<<ans<<endl;
      return 0;
    }

      

  • 相关阅读:
    Windows7驱动调试小Tips
    [Sencha ExtJS &amp; Touch] 在Sencha(Extjs/Touch)应用程序中使用plugins(插件)和mixins(混入)
    C语言开发函数库时利用不透明指针对外隐藏结构体细节
    CLLocationManagerDelegate的解说
    RecyclerView的使用(1)之HelloWorld
    黑马day07 登录注冊案例(一)
    在互联网公司和行业软件公司上班,有什么差别?
    RHEL7 -- systemd
    RHEL7 -- 识别文件系统和设备
    11G新特性 -- 块介质恢复性能增强(block media recovery)
  • 原文地址:https://www.cnblogs.com/AseanA/p/6612419.html
Copyright © 2020-2023  润新知