poj 3415

来源:互联网 发布:自己淘宝店铺的链接 编辑:程序博客网 时间:2024/06/11 13:00

单调队列+后缀数组

#include <iostream>#include <cstdio>#include <cstring>using namespace std;const int maxn=2e5+19;int r[maxn];int *rank,height[maxn],sa[maxn];int wx[maxn],wy[maxn],cnt[maxn];char a[maxn],b[maxn];struct{    long long sum1,sum2,data;}stack[maxn];inline bool cmp(int *r,int a,int b,int l){    return r[a]==r[b]&&r[a+l]==r[b+l];}void da(int *r,int n,int m){    int i,l,p,*x=wx,*y=wy,*t;    memset(cnt,0,sizeof(int)*(m+1));    for(int i=1;i<=n;i++) cnt[x[i]=r[i]]++;    for(int i=1;i<=m;i++) cnt[i]+=cnt[i-1];    for(int i=n;i>=1;i--) sa[cnt[x[i]]--]=i;    for(l=1,p=1;p<n;l<<=1,m=p)    {        for(p=1,i=n-l+1;i<=n;i++) y[p++]=i;        for(i=1;i<=n;i++)        if(sa[i]>l)        y[p++]=sa[i]-l;        memset(cnt,0,sizeof(int)*(m+1));        for(i=1;i<=n;i++) cnt[x[i]]++;        for(i=1;i<=m;i++) cnt[i]+=cnt[i-1];        for(i=n;i>=1;i--) sa[cnt[x[y[i]]]--]=y[i];        for(t=x,x=y,y=t,p=1,x[sa[1]]=1,i=2;i<=n;i++)        if(max(sa[i-1],sa[i])+l<=n)        x[sa[i]]=cmp(y,sa[i-1],sa[i],l)?p:++p;        else        x[sa[i]]=++p;    }    rank=x;    int j,k=0;for(i=1;i<=n;height[rank[i++]]=k)for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);return;}int main(){//    freopen("in.txt","r",stdin);    int n;    while(scanf("%d",&n),n)    {        scanf("%s",a+1);        scanf("%s",b+1);        {            int n1=strlen(a+1);            int n2=strlen(b+1);            for(int i=1;i<=n1;i++)            r[i]=a[i];            r[n1+1]='#';            for(int i=1;i<=n2;i++)            r[n1+i+1]=b[i];            da(r,n1+n2+1,128);            long long ans=0,ret1=0,ret2=0,sum1,sum2;            int end=0;            for(int i=2;i<=n1+n2+1;i++)            {                if(height[i]<n)                {                    end=0;                    ret1=0;                    ret2=0;                    continue;                }                sum1=0,sum2=0;                while(end>0&&stack[end].data>=height[i]-n+1)                {                    sum1+=stack[end].sum1;                    sum2+=stack[end].sum2;                    ret1-=stack[end].data*stack[end].sum1;                    ret2-=stack[end].data*stack[end].sum2;                    end--;                }                if(sa[i-1]<=n1) sum1++;                else sum2++;                stack[++end].data=height[i]-n+1;                stack[end].sum1=sum1;                stack[end].sum2=sum2;                ret1+=stack[end].data*sum1;                ret2+=stack[end].data*sum2;                if(sa[i]<=n1) ans+=ret2;                else ans+=ret1;            }            printf("%lld\n",ans);        }    }    return 0;}