zoukankan      html  css  js  c++  java
  • spoj 1812 LCS2(SAM+DP)

    求若干个串的最长公共子串。

    SAM+DP

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

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

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

     1 #include<cstdio>
     2 #include<cstring>
     3 using namespace std;
     4 
     5 const int N = 5*1e5+10;
     6 
     7 char s[N];
     8 int sz,last,root,l[N],ch[N][26],fa[N],mn[N],mx[N];
     9 int b[N],cnt[N];
    10 void add(int x) {
    11     int c=s[x]-'a';
    12     int p=last,np=++sz; last=np; 
    13     l[np]=mn[np]=x+1;
    14     for(;p&&!ch[p][c];p=fa[p]) ch[p][c]=np;
    15     if(!p) fa[np]=root;
    16     else {
    17         int q=ch[p][c];
    18         if(l[p]+1==l[q]) fa[np]=q;
    19         else {
    20             int nq=++sz; l[nq]=mn[nq]=l[p]+1;
    21             memcpy(ch[nq],ch[q],sizeof(ch[q]));
    22             fa[nq]=fa[q];
    23             fa[np]=fa[q]=nq;
    24             for(;ch[p][c]==q;p=fa[p]) ch[p][c]=nq;
    25         }
    26     }
    27 }
    28 
    29 int main() {
    30     root=last=++sz;
    31     scanf("%s",s);
    32     int len=strlen(s);
    33     for(int i=0;i<len;i++) add(i);
    34     for(int i=1;i<=sz;i++) cnt[l[i]]++;
    35     for(int i=1;i<=len;i++) cnt[i]+=cnt[i-1];
    36     for(int i=1;i<=sz;i++) b[cnt[l[i]]--]=i;
    37     while(scanf("%s",s)==1) {
    38         int p=root; len=0;
    39         for(int i=0;s[i];i++) {
    40             int c=s[i]-'a';
    41             if(ch[p][c]) { len++; p=ch[p][c]; }
    42             else {
    43                 while(p&&!ch[p][c]) p=fa[p];
    44                 if(!p) { len=0; p=root; }
    45                 else { len=l[p]+1; p=ch[p][c]; }
    46             }
    47             if(len>mx[p]) mx[p]=len;
    48         }
    49         for(int i=sz;i;i--) {
    50             p=b[i];
    51             if(mx[p]<mn[p]) mn[p]=mx[p];
    52             if(fa[p] && mx[fa[p]]<mx[p]) mx[fa[p]]=mx[p];
    53             mx[p]=0;
    54         }
    55     }
    56     int ans=0;
    57     for(int i=1;i<=sz;i++)
    58         if(mn[i]>ans) ans=mn[i];
    59     printf("%d",ans);
    60     return 0;
    61 }

    先将一个串建SAM,然后用后面的串去匹配,对于每一个串,保存最大值,对于不同的串,更新最小值。

    SAM结点多两个值,ml表示多个串的最小值,nl表示当前串匹配的最大值。

      1 #include <iostream>
      2 #include <string.h>
      3 #include <algorithm>
      4 #include <stdio.h>
      5 
      6 using namespace std;
      7 const int N=250005;
      8 
      9 struct State
     10 {
     11     State *pre,*go[26];
     12     int step,nl,ml;
     13     void clear()
     14     {
     15         pre=0;
     16         step=0;
     17         memset(go,0,sizeof(go));
     18     }
     19 }*root,*last;
     20 
     21 State statePool[N*2],*b[2*N],*cur;
     22 
     23 void init()
     24 {
     25     cur=statePool;
     26     root=last=cur++;
     27     root->clear();
     28 }
     29 
     30 void Insert(int w)
     31 {
     32     State *p=last;
     33     State *np=cur++;
     34     np->clear();
     35     np->step=np->ml=p->step+1;
     36     while(p&&!p->go[w])
     37         p->go[w]=np,p=p->pre;
     38     if(p==0)
     39         np->pre=root;
     40     else
     41     {
     42         State *q=p->go[w];
     43         if(p->step+1==q->step)
     44             np->pre=q;
     45         else
     46         {
     47             State *nq=cur++;
     48             nq->clear();
     49             memcpy(nq->go,q->go,sizeof(q->go));
     50             nq->step=nq->ml=p->step+1;
     51             nq->pre=q->pre;
     52             q->pre=nq;
     53             np->pre=nq;
     54             while(p&&p->go[w]==q)
     55                 p->go[w]=nq, p=p->pre;
     56         }
     57     }
     58     last=np;
     59 }
     60 
     61 char str[N];
     62 int cnt[N];
     63 
     64 int main()
     65 {
     66     int n,m;
     67     scanf("%s",str);
     68     n=strlen(str);
     69     init();
     70     for(int i=0; i<n; i++)
     71         Insert(str[i]-'a');
     72     for(State *p=statePool; p!=cur; p++)
     73         cnt[p->step]++;
     74     for(int i=1; i<=n; i++)
     75         cnt[i]+=cnt[i-1];
     76     for(State *p=statePool; p!=cur; p++)
     77         b[--cnt[p->step]]=p;
     78     while(~scanf("%s",str))
     79     {
     80         int len=0;
     81         m=strlen(str);
     82         State *p=root;
     83         for(int i=0; i<m; i++)
     84         {
     85             int x=str[i]-'a';
     86             if(p->go[x])
     87             {
     88                 len++;
     89                 p=p->go[x];
     90             }
     91             else
     92             {
     93                 while(p&&!p->go[x]) p=p->pre;
     94                 if(!p) p=root,len=0;
     95                 else   len=p->step+1,p=p->go[x];
     96             }
     97             if(len>p->nl) p->nl=len;
     98         }
     99         int num=cur-statePool;
    100         for(int i=num-1;i>=0;i--)
    101         {
    102             p=b[i];
    103             if(p->ml>p->nl) p->ml=p->nl;
    104             if(p->pre&&p->pre->nl<p->nl) p->pre->nl=p->nl;
    105             p->nl=0;
    106         }
    107     }
    108     int ans=0;
    109     for(State *p=statePool;p!=cur;p++)
    110         if(p->ml>ans) ans=p->ml;
    111     printf("%d
    ",ans);
    112     return 0;
    113 }
  • 相关阅读:
    HTTP的OPTIONS请求方法
    K8s -- DaemonSet
    Nginx 变量漫谈(二)
    Nginx 变量漫谈(一)
    通俗地讲,Netty 能做什么?
    CSP AFO后可以公开的情报
    AT1219 歴史の研究
    LuoguP4165 [SCOI2007]组队
    CF708C Centroids(树形DP)
    CF208E Blood Cousins(DSU,倍增)
  • 原文地址:https://www.cnblogs.com/agenthtb/p/7696151.html
Copyright © 2011-2022 走看看