3238: [Ahoi2013]差异

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 2357  Solved: 1067
[Submit][Status][Discuss]

Description

Input

一行,一个字符串S

Output

 

一行,一个整数,表示所求值

Sample Input

cacao

Sample Output


54

HINT

 



2<=N<=500000,S由小写英文字母组成

 

Source

[Submit][Status][Discuss]

 

后缀数组+单调栈

今天终于学了后缀数组 记得去年的寒假 zjw学长给我们讲过这个东西 那时连倍增是什么都不知道。。。

我的后缀数组 是 nlog2n的 (因为我不会那个什么基数排序)

题目是道裸题 可以练练手

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define For(i,x,y) for(int i=x;i<=y;++i)
const int N = 500005;
using namespace std;
char s[N];
int sa[N],rk[N],h[N];
int Log[N];int n;
int st[N][20];
struct data{
    int i,x,y;
    bool operator < (const data&a)const{
        return (x<a.x||x==a.x&&y<a.y);
    }
    bool operator != (const data&a)const{
        return (x!=a.x||y!=a.y);
    }
}a[N];
void calh(){
    int i,k=0,j;
    For(i,1,n) rk[sa[i]]=i;
    for(i=1;i<=n;h[rk[i++]]=k)
    {
        if(k>0)k--;int j=sa[rk[i]-1];
        while(s[i+k]==s[j+k])k++;
    }
             
    return;
}
//int lcp(int x,int y){
//    if(x==y)return n-x+1;
//    x=rk[x];y=rk[y];
//    if(x>y){x^=y;y^=x;x^=y;}
//    int len=y-x;x++;
//    return min(st[x][Log[len]],st[1+y-1<<Log[len]][Log[len]]);
//}
long long q[N],qsum[N];
int main()
{
//  freopen("sa.in","r",stdin);
//  freopen("sa.out","w",stdout);
    scanf("%s",s+1);
    n=strlen(s+1);
    For(i,1,n)rk[i]=s[i];
    For(i,2,N-1)Log[i]=Log[i>>1]+1;
    memset(st,127,sizeof(st));
    for(int j=0;j<=Log[n]+1;++j){
        For(i,1,n) a[i]=(data){i,rk[i],rk[i+(1<<j)]};
        sort(a+1,a+n+1);int k=1;
        For(i,1,n){
            rk[a[i].i]=k;
            if(a[i]!=a[i+1])k++;
        }
    }
    For(i,1,n)sa[rk[i]]=i;
    calh();
//  For(i,1,n)printf("%d ",h[i]);
//  For(i,1,n)st[i][0]=h[i];
//  for(int j=1;j<=Log[n]+1;++j){
//      For(i,1,n){
//          if(i+(1<<j-1)>n)break;
//          st[i][j]=min(st[i][j-1],st[i+(1<<j-1)][j-1]);
//      }
//  }
    long long ans=0;
    int r=0;long long sum=0;
    For(i,1,n){
        long long tsum=1;
        while(r>0&&q[r]>h[i])
            sum=sum-q[r]*qsum[r],tsum+=qsum[r],r--;
        q[++r]=h[i];qsum[r]=tsum;sum+=tsum*h[i];
        ans-=2*sum;
    }
    For(i,1,n) ans+=1LL*i*(n-1);
    cout<<ans;
    return 0;
}

 

 posted on 2017-01-09 21:39  rwy  阅读(126)  评论(0编辑  收藏  举报