后缀数组求lcp(模版,st模版把

来源:互联网 发布:期货和股票的区别 知乎 编辑:程序博客网 时间:2024/05/21 09:12

算模版?,不过这东西,顺着思路很好写啊

题目读不懂。。。所以只有rmq和后缀数组是我写的,但是我也是想联系一下后缀数组求lcp,其实没法说吧,顺着st算法的理论写就行


不过为什么log求rmq_st的k,会wa,但是循环判断就不会?????

#include<cstdio>#include<cstring>#include<algorithm>#include<cstdlib>#include<cmath>#include<iostream>#define M(x) memset(x,0,sizeof(x))using namespace std;const int N=100005;int sa[N],c[N],t1[N],t2[N],s[N],height[N],rk[N],f[N][22],n;char ch[N];void clear(){M(sa);M(c);M(t1);M(t2);M(height);M(rk);M(f);M(s);}void build_sa()  {      int m=29,*x=t1,*y=t2;      for (int i=0;i<m;i++) c[i]=0;      for (int i=0;i<n;i++) c[x[i]=s[i]]++;      for (int i=1;i<m;i++) c[i]+=c[i-1];      for (int i=n-1;i>=0;i--) sa[--c[x[i]]]=i;            for (int k=1;k<=n;k<<=1)      {          int p=0;          for (int i=n-k;i<n;i++) y[p++]=i;          for (int i=0;i<n;i++) if (sa[i]>=k) y[p++]=sa[i]-k;                    for (int i=0;i<m;i++) c[i]=0;          for (int i=0;i<n;i++) c[x[y[i]]]++;          for (int i=1;i<m;i++) c[i]+=c[i-1];          for (int i=n-1;i>=0;i--) sa[--c[x[y[i]]]]=y[i];          swap(x,y);          x[sa[0]]=0;p=1;          for (int i=1;i<n;i++)          x[sa[i]]=y[sa[i]]==y[sa[i-1]]&&y[sa[i]+k]==y[sa[i-1]+k]?p-1:p++;          if (p>=n) break;          m=p;       }  }  void build_height()  {      int k=0;     for (int i=0;i<n;i++) rk[sa[i]]=i;      for (int i=0;i<n-1;i++)      {          if (k) k--;          int j=sa[rk[i]-1];          while (s[j+k]==s[i+k]) k++;          height[rk[i]]=k;      }  }  void build_st(){for (int i=0;i<n;i++) f[i][0]=height[i];for (int k=1;(1<<k)<=n;k++)for (int i=0;i<n;i++)if (i+(1<<k)-1<n) f[i][k]=min(f[i][k-1],f[i+(1<<(k-1))][k-1]);  }//预处理,第0名其实是不用算的,因为第0名是哨兵元素啊,我们需用的都是排在1~n-1之间的元素 int query_RMQ(int u,int v){int l=rk[u],r=rk[v];if (l>r) swap(l,r);l++;int k=0;while((1<<(1+k))<=r-l+1) k++;///为什么我用log过不了???,这里就是只要2^k乘2<=长度,那么就再把k++return min(f[l][k],f[r-(1<<k)+1][k]);}//rmq  int change(int a)  {       if(a<10) return 1;      else if(a<100) return 2;      else if(a<1000) return 3;      else if(a<10000) return 4;      else if(a<100000) return 5;  }  int main ()  {      while(scanf("%s",ch)!=EOF)      {          n=strlen(ch);          for(int i=0;i<n;++i)              s[i]=ch[i]-'a'+1;          s[n++]=0;        build_sa();          build_height();          build_st();              int q;scanf("%d",&q);          long long len1=0,len2=0;          for(int kk=1,u,v,lcp,preu=-1,prev=-1;kk<=q;++kk)          {              scanf("%d%d",&u,&v);              if(preu>=0)              {                  if(u==preu)                      lcp=n-u;                  else lcp=query_RMQ(u,preu);                  lcp=min(lcp,min(v-u,prev-preu));                  len2+=change(lcp)+v-u-lcp;              }              else len2+=1+v-u;              len1+=v-u+1;              len2+=2;              preu=u;prev=v;          }          cout<<len1<<' '<<len2<<endl;      }      return 0;  }  


0 0
原创粉丝点击