SPOJ 1812 LCS2

题解:

和上一题差不多

每个点记录前面的到这个点的最大值

初值赋为len[i]

然后注意要用子节点更新父节点

代码:

#include <bits/stdc++.h>
#define ll long long
#define rint register int
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
#define me(x) memset(x,0,sizeof(x))
using namespace std;
const int N=3e6;
const int INF=1e9;
char s[N];
int size[N],len[N],ch[N][26];
int lst=1,node=1,t[N],a[N],fa[N],ans[N],ans2[N],num[N];
void extend(int c)
{
  int f=lst,p=++node; lst=p;
  len[p]=len[f]+1; size[p]=1;
  while (f&&!ch[f][c]) ch[f][c]=p,f=fa[f];
  if (!f) { fa[p]=1; return;};
  int x=ch[f][c],y=++node;
  if (len[f]+1==len[x]) {fa[p]=x; node--;return;};
  len[y]=len[f]+1; fa[y]=fa[x]; fa[x]=fa[p]=y;
  memcpy(ch[y],ch[x],sizeof(ch[x]));
  while (f&&ch[f][c]==x) ch[f][c]=y,f=fa[f];
}
void js()
{
  int l=strlen(s),now=1,t=0;
  rep(i,1,l)
  {
    int x=s[i-1]-'a';
    if (ch[now][x]) now=ch[now][x],++t;
    else 
    {
      while (now&&!ch[now][x]) now=fa[now];
      if (!now) now=1,t=0;
      else t=len[now]+1,now=ch[now][x];
    }
    ans[now]=max(ans[now],t);
  }
}
int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  ios::sync_with_stdio(false);
  cin>>s;
  int l=strlen(s);
  rep(i,1,l) extend(s[i-1]-'a');
  rep(i,1,node) t[len[i]]++;
  rep(i,1,node) t[i]+=t[i-1];
  rep(i,1,node) a[t[len[i]]--]=i;
  rep(i,1,N-1) ans2[i]=len[i];
  while (cin>>s)
  {
    me(ans);
    js();
    dep(i,node,1)
    {
      int x=a[i];
      ans2[x]=min(ans2[x],ans[x]);
      ans[fa[x]]=max(ans[fa[x]],ans[x]);
    }
  }
  int maxn=0;
  rep(i,1,node) maxn=max(maxn,ans2[i]);
  cout<<maxn<<endl;
  return 0;
}

 

posted @ 2018-07-21 16:19  尹吴潇  阅读(103)  评论(0编辑  收藏  举报