zoukankan      html  css  js  c++  java
  • bzoj3879

    题解:

    SA是唯一听懂了怎么求的东西

    显然对每个询问只把询问到的那些位置拉出来用单调栈维护就行了

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=500005;
    char s[N];
    int sa[N],rank[N],height[N],cnt[N],f[N],a[N*6],sta[N],mn[N][25],log[N],num[N],n,q,m=26;
    int get(int l,int r)
    {
        int k=log[r-l+1];
        return min(mn[l][k],mn[r-(1<<k)+1][k]);
    }
    int main()
    {
        ll now,ans;
        int x,p,top,tot;
        scanf("%d%d",&n,&q);
        scanf("%s",s+1);
        for (int i=1;i<=n;i++)cnt[rank[i]=f[i]=s[i]-'a'+1]++;
        for (int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
        for (int i=n;i;i--)sa[cnt[f[i]]--]=i;
        for (int k=1;k<=n;k<<=1)
         {
             p=0;
             for (int i=n-k+1;i<=n;i++)f[++p]=i;
             for (int i=1;i<=n;i++)
              if (sa[i]>k)f[++p]=sa[i]-k;
             for (int i=1;i<=m;i++)cnt[i]=0;
            for (int i=1;i<=n;i++)cnt[rank[f[i]]]++;
            for (int i=1;i<=m;i++)cnt[i]+=cnt[i-1];
            for (int i=n;i;i--)sa[cnt[rank[f[i]]]--]=f[i];
            for (int i=1;i<=n;i++)f[i]=rank[i];
            rank[sa[1]]=1;
            for (int i=2;i<=n;i++)
             if (f[sa[i]]!=f[sa[i-1]]||f[sa[i]+k]!=f[sa[i-1]+k])
              rank[sa[i]]=rank[sa[i-1]]+1;
             else rank[sa[i]]=rank[sa[i-1]];
            m=rank[sa[n]];
            if (m>=n)break; 
         }
        for (int i=1;i<=n;i++)
         {
             height[rank[i]]=height[rank[i-1]];
             if (height[rank[i]])height[rank[i]]--;
             while (s[i+height[rank[i]]]==s[sa[rank[i]-1]+height[rank[i]]])
              height[rank[i]]++;
         } 
        for (int i=1;i<=n;i++)mn[i][0]=height[i];
        for (int k=1;(1<<k)<=n;k++)log[1<<k]=k;
        for (int i=3;i<=n;i++)
         if (!log[i])log[i]=log[i-1];
        for (int k=1;(1<<k)<=n;k++)
         for (int i=1;i+(1<<k)-1<=n;i++)
          mn[i][k]=min(mn[i][k-1],mn[i+(1<<k-1)][k-1]);
        while (q--)
         {
             scanf("%d",&m);
             for (int i=1;i<=m;i++)
              {
                  scanf("%d",&x);
                  a[i]=rank[x];
             }
            sort(a+1,a+m+1);
            m=unique(a+1,a+m+1)-a-1;
            now=sta[top=1]=n-sa[a[1]]+1;
            ans=0;
            num[1]=1;
            for (int i=2;i<=m;i++)
             {
                 x=get(a[i-1]+1,a[i]);
                 tot=0;
                 while (top&&x<=sta[top])
                  {
                      now-=(ll)num[top]*sta[top];
                      tot+=num[top];
                      top--;
                 }
                now+=(ll)x*tot;
                ans+=now;
                sta[++top]=x;
                num[top]=tot;
                sta[++top]=n-sa[a[i]]+1;
                num[top]=1;
                now+=sta[top];
             } 
            printf("%lld
    ",ans); 
         }   
    }
  • 相关阅读:
    渗透学习——资料整理
    c语言——运算符、分支结构、循环结构
    c语言——字符串变量、函数
    总结Java开发者经常会犯的前十种错误
    项目开发遇到的问题及其解决.总结
    Java开发者写SQL时常犯的10个错误
    Java开发中常见的异常问题
    Java编程:常见问题汇总
    Exploded location overlaps an existing deployment解决办法
    Eclipse下svn的创建分支/合并/切换使用
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8473266.html
Copyright © 2011-2022 走看看