bzoj1396 识别子串

Posted yinwuxiao

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj1396 识别子串相关的知识,希望对你有一定的参考价值。

题解:

首先我们知道对于size==1的点是只出现一次的

存疑:为什么新增点不会size==1

那么问题就变成区间取等差数列,区间取最小值

分别线段树维护就可以了

代码:

 

#include <bits/stdc++.h>
#define IL inline
#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--)
using namespace std;
const int INF=1e9;
const int N=3e5;
char s[N];
int size[N],len[N],ch[N][26];
int lst=1,node=1,t[N],a[N],fa[N],pos[N],pl;
void extend(int c)
{
  int f=lst;
  if (ch[f][c]&&len[ch[f][c]]==len[f]+1)
  { 
    lst=ch[f][c];
    return;
  }
  int p=++node; lst=p;
  len[p]=len[f]+1; //size[p][pl]=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];
}
IL int min(int x,int y)
{
  if (x>y) return(y); else return(x);
}
IL int max(int x,int y)
{
  if (x<y) return(y); else return(x);
}
IL void minn(int &x,int y)
{
  if (x>y) x=y;
}
IL void maxn(int &x,int y)
{
  if (x<y) x=y;
}
const int N1=N*4;
struct sgt{
  int lazy1[N1],lazy2[N1];
  sgt()
  {
    rep(i,0,N1-1) lazy1[i]=lazy2[i]=INF;
  }
  #define mid ((h+t)/2)
  IL void down(int x,int h,int t)
  {
    minn(lazy1[x*2],lazy1[x]);
    minn(lazy1[x*2+1],lazy1[x]-(mid-h+1));
    minn(lazy2[x*2],lazy2[x]);
    minn(lazy2[x*2+1],lazy2[x]);
  }
  void change1(int x,int h,int t,int h1,int t1,int k)
  {
    if (h1<=h&&t<=t1)
    {
      minn(lazy1[x],k); return;
    }
    down(x,h,t);
    if (h1<=mid) change1(x*2,h,mid,h1,t1,k);
    if (mid<t1) change1(x*2+1,mid+1,t,h1,t1,k-(mid-h+1));
  }
  void change2(int x,int h,int t,int h1,int t1,int k)
  {
    if (h1<=h&&t<=t1)
    {
      minn(lazy2[x],k); return;
    }
    down(x,h,t);
    if (h1<=mid) change2(x*2,h,mid,h1,t1,k);
    if (mid<t1) change2(x*2+1,mid+1,t,h1,t1,k);
  }
  int query(int x,int h,int t,int pos)
  {
    if (h==t)
    {
      return(min(lazy1[x],lazy2[x]));
    }
    down(x,h,t);
    if (pos<=mid) return(query(x*2,h,mid,pos));
    else return(query(x*2+1,mid+1,t,pos));
  }
}S;
int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  ios::sync_with_stdio(false);
  cin>>s;
  int l=strlen(s);
  int n=l;
  rep(i,1,l) extend(s[i-1]-a),size[lst]++,pos[lst]=i;
  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;
  dep(i,node,1)
  {
    int x=a[i];
    size[fa[x]]+=size[x];   
  }
  rep(i,1,node)
  if (size[i]==1)
  {
    S.change1(1,1,n,pos[i]-len[i]+1,pos[i]-len[fa[i]],len[i]);
    if (fa[i]) S.change2(1,1,n,pos[i]-len[fa[i]]+1,pos[i],1+len[fa[i]]);
  }
  rep(i,1,n)
    cout<<S.query(1,1,n,i)<<endl;
  return 0; 
} 

 

以上是关于bzoj1396 识别子串的主要内容,如果未能解决你的问题,请参考以下文章

bzoj1396 识别子串

BZOJ 1396:识别子串 SA+树状数组+单调队列

bzoj1396: 识别子串

[BZOJ1396]识别子串 后缀自动机+线段树

●BZOJ 1396 识别子串

bzoj1396 识别子串