zoukankan      html  css  js  c++  java
  • bzoj3879

    题解:

    后缀数组

    然后把读入的内容去重,按照rank排序

    然后用单调栈处理一下

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=500010;
    const ll M=23333333333333333ll;
    int r[N],ra[N],rb[N],a,st[N],h[N],sa[N],rank[N],n,m,Q;
    int q[N],t,ls[N],rs[N],f[N][20],Log[N],vis[N],v[N],s[N];
    ll ans;
    char str[N];
    void build()
    {
        int *x=ra,*y=rb;
        for (int i=0;i<n;i++)st[x[i]=r[i]]++;
        for (int i=1;i<m;i++)st[i]+=st[i-1];
        for (int i=n-1;i>=0;i--)  sa[--st[x[i]]]=i;
        for (int j=1,p=1;p<n;j<<=1,m=p)
         {
             p=0;
            for (int i=n-j;i<n;i++)y[p++]=i;
            for (int i=0;i<n;i++)
             if (sa[i]>=j)y[p++]=sa[i]-j;
            for (int i=0;i<m;i++)st[i]=0;
            for (int i=0;i<n;i++)st[x[y[i]]]++;
            for (int i=1;i<m;i++)st[i]+=st[i-1];
            for (int i=n-1;i>=0;i--)sa[--st[x[y[i]]]]=y[i];
            swap(x,y);x[sa[0]]=0;        
            for (int i=p=1;i<n;i++)
             x[sa[i]]=(y[sa[i]]==y[sa[i-1]]&&y[sa[i]+j]==y[sa[i-1]+j])?p-1:p++;
         }
        for (int i=1;i<n;i++)rank[sa[i]]=i;
        for (int i=0,k=0;i<n-1;h[rank[i++]]=k)
         {
             if (k)k--;
             for (int j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
         }
    }
    int cmp(int a,int b){return rank[a]<rank[b];}
    int query(int a,int b)
    {
        int k=Log[b-a+1];
        return min(f[a][k],f[b-(1<<k)+1][k]);
    }
    int main()
    {
        scanf("%d%d%s",&n,&Q,str);
        for (int i=0;i<n;i++)r[i]=str[i]-'a'+1;
        n++;m=27;build();n--;
        for (int i=1;i<=n;i++)f[i][0]=h[i];
        for (int j=1;(1<<j)<n;j++)
         for (int i=1;i+(1<<j)-1<=n;i++)f[i][j]=min(f[i][j-1],f[i+(1<<j-1)][j-1]);
        for (int i=2;i<=n;i++)Log[i]=Log[i>>1]+1;
        while (Q--)
         {
            scanf("%d",&a);
            for (int j=1;j<=a;j++)
             {
                scanf("%d",&v[j]);
                v[j]--;
                if (vis[v[j]])j--,a--;
                vis[v[j]]=1;
             }
            sort(v+1,v+a+1,cmp);
            for (int j=1;j<a;j++)s[j]=query(rank[v[j]]+1,rank[v[j+1]]);
            s[0]=s[a]=-1;q[1]=0;t=1;
            for (int j=1;j<a;j++)
             {
                while (t&&s[q[t]]>s[j])t--;
                ls[j]=q[t],q[++t]=j;
             }
            t=1,q[1]=a;
            for (int j=a-1;j>0;j--)
             {
                while (t&&s[q[t]]>=s[j])t--;
                rs[j]=q[t],q[++t]=j;
             }
            ans=0;
            for (int j=1;j<a;j++)ans=(ans+(ll)(j-ls[j])*(rs[j]-j)*s[j])%M;
            printf("%lld
    ",ans);
            for (int j=1;j<=a;j++)vis[v[j]]=0;
         }
    }
  • 相关阅读:
    .NET自动化测试手记(2) 实例:点击计算器按钮
    解决httpwebrequest无法通过使用代理的局域网获取response的问题
    iOS开发之SQLite
    iOS开发之AVAudioPlayer 音频播放
    iOS开发 键盘添加工具条(toolbar)
    UIPickerView中的实例方法
    TextField
    UISearchBar和UISearchDisplayController
    Objectivec 字符串遍历的几种方法
    《Write ObjectiveC Code》学习笔记
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8503758.html
Copyright © 2011-2022 走看看