bzoj 3879: SvT

题目

如果直接用后缀树的话,就得建出来然后跑虚树什么的了,很麻烦

但是用后缀数组可以规约到一类问题里面http://www.cnblogs.com/hehe54321/p/8666859.html

每次询问一个集合的话,只需要把有关的内容抽离出来就好了

为什么比别人的后缀树+虚树还要长啊

错误记录:拖板子忘了改49行的数据范围(1000000没改成500000)

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<string>
  4 #define md 23333333333333333
  5 using namespace std;
  6 typedef long long LL;
  7 string txt;
  8 namespace SA
  9 {
 10     int n,p,m=128,sa[500100],t1[500100],t2[500100],cnt[500100],*x=t1,*y=t2;
 11     int *height=t2,*rk=t1;
 12     int st[500100][21],log2x[500100],lft[21];
 13     const int log2n=20;
 14     void build()
 15     {
 16         int i,k;
 17         n=txt.length();
 18         for(i=0;i<n;i++)    cnt[x[i]=txt[i]]++;
 19         for(i=1;i<m;i++)    cnt[i]+=cnt[i-1];
 20         for(i=n-1;i>=0;i--)    sa[--cnt[x[i]]]=i;
 21         for(k=1;k<=n;k<<=1)
 22         {
 23             p=0;
 24             for(i=n-k;i<n;i++)    y[p++]=i;
 25             for(i=0;i<n;i++)    if(sa[i]>=k)    y[p++]=sa[i]-k;
 26             for(i=0;i<m;i++)    cnt[i]=0;
 27             for(i=0;i<n;i++)    cnt[x[y[i]]]++;
 28             for(i=1;i<m;i++)    cnt[i]+=cnt[i-1];
 29             for(i=n-1;i>=0;i--)    sa[--cnt[x[y[i]]]]=y[i];
 30             swap(x,y);p=0;
 31             x[sa[0]]=0;
 32             for(i=1;i<n;i++)
 33                 x[sa[i]]=y[sa[i]]==y[sa[i-1]]
 34                 &&(sa[i]+k<n?y[sa[i]+k]:0)==(sa[i-1]+k<n?y[sa[i-1]+k]:0)
 35                 ?p:++p;
 36             if(p>=n)    break;
 37             m=p+1;
 38         }
 39         for(i=0;i<n;i++)    rk[sa[i]]=i;
 40         for(i=0,k=0;i<n;i++)
 41         {
 42             if(k)    k--;
 43             if(rk[i])
 44                 while(sa[rk[i]-1]+k<n&&i+k<n&&txt[sa[rk[i]-1]+k]==txt[i+k])    k++;
 45             height[rk[i]]=k;
 46         }
 47         lft[0]=1;for(i=1;i<=log2n;i++)    lft[i]=lft[i-1]<<1;
 48         log2x[1]=k=0;
 49         for(i=2;i<=500000;i++)
 50         {
 51             if(i>=lft[k+1])    ++k;
 52             log2x[i]=k;
 53         }
 54         for(i=0;i<n;i++)    st[i][0]=height[i];
 55         for(k=1;k<=log2n;k++)
 56             for(i=0;i<n-lft[k]+1;i++)
 57                 st[i][k]=min(st[i][k-1],st[i+lft[k-1]][k-1]);
 58     }
 59     int lcp(int l,int r)
 60     {
 61         //if(l==r)    return n-l;
 62         //l=rk[l];r=rk[r];
 63         if(l>r) swap(l,r);
 64         l++;int k=log2x[r-l+1];
 65         return min(st[l][k],st[r-lft[k]+1][k]);
 66     }
 67 }
 68 struct Info
 69 {
 70     int pos,dep;
 71     Info(int a,int b):pos(a),dep(b){}
 72     Info():pos(0),dep(0){}
 73 }b[3000100];
 74 bool operator<(const Info& a,const Info& b)
 75 {
 76     return a.dep>b.dep;
 77 }
 78 int n,m,num,a[3000100],sz[3000100],fa[3000100];LL ans;
 79 int find(int x)    {return x==fa[x]?x:fa[x]=find(fa[x]);}
 80 int main()
 81 {
 82     ios::sync_with_stdio(0);
 83     int i,d,t,fx,fy;
 84     cin>>n>>m;cin>>txt;
 85     SA::build();
 86     while(m--)
 87     {
 88         cin>>num;
 89         for(i=1;i<=num;i++)    cin>>a[i],a[i]=SA::rk[a[i]-1];
 90         sort(a+1,a+num+1);num=unique(a+1,a+num+1)-a-1;
 91         if(num<=1)    {cout<<0<<'\n';continue;}
 92         for(i=2;i<=num;i++)    b[i]=Info(i,SA::lcp(a[i],a[i-1]));
 93         for(i=1;i<=num;i++)    fa[i]=i,sz[i]=1;
 94         sort(b+2,b+num+1);ans=0;
 95         for(i=2;i<=num;i++)
 96         {
 97             d=b[i].dep;t=b[i].pos;
 98             fx=find(t-1);fy=find(t);
 99             ans=(ans+(LL)d*sz[fx]*sz[fy])%md;
100             sz[fy]+=sz[fx];fa[fx]=fy;
101         }
102         cout<<ans<<'\n';
103     }
104     return 0;
105 }
posted @ 2018-03-29 14:20  hehe_54321  阅读(84)  评论(0编辑  收藏  举报
AmazingCounters.com