BZOJ3238: [Ahoi2013]差异 (后缀自动机)

本文介绍了一种利用后缀自动机解决特定字符串问题的方法,并提供了一份详细的代码实现。此外,还给出了另一种使用后缀数组的解法,通过两次单调栈解决了区间最小值问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Description

Input

一行,一个字符串S

Output

 

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

Sample Input

cacao

Sample Output


54

HINT

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

YY了后缀自动机的解法:

首先题意就是让你求sigma(LCP(i,j)|i<j)

将字符串反过来,考虑两个后缀对答案的贡献,其实就是节点x和y的lca节点包含的最长子串长度

那么将SAM构出来,考虑当LCA为节点z时,有多少满足条件的(x,y),这个枚举z的相邻子节点,dp一下即可

code:O(n) 2104ms

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=1000010;
int n,to[maxn][26],fa[maxn],l[maxn],f[maxn],x[maxn],w[maxn],od[maxn],cnt=1,last=1;
void extend(int c)
{
    int p,q,np,nq;
    p=last;last=np=++cnt;l[np]=l[p]+1;f[np]=w[np]=1;
    for(;!to[p][c];p=fa[p]) to[p][c]=np;
    if(!p) fa[np]=1;
    else
    {
        q=to[p][c];
        if(l[p]+1==l[q]) fa[np]=q;
        else
        {
            nq=++cnt;l[nq]=l[p]+1;
            memcpy(to[nq],to[q],sizeof(to[q]));
            fa[nq]=fa[q];
            fa[q]=fa[np]=nq;
            for(;to[p][c]==q;p=fa[p]) to[p][c]=nq;
        }
    }
}
LL solve()
{
    LL ans=0;
    for(int i=1;i<=cnt;i++) x[l[i]]++;
    for(int i=1;i<=n;i++) x[i]+=x[i-1];
    for(int i=1;i<=cnt;i++) od[x[l[i]]--]=i;
    for(int i=cnt;i;i--) f[fa[od[i]]]+=f[od[i]];
    for(int i=1;i<=cnt;i++)
    {
        ans+=(LL)w[fa[i]]*f[i]*l[fa[i]];
        w[fa[i]]+=f[i];
    }
    return ans;
}
char s[maxn];
int main()
{
    scanf("%s",s);
    n=strlen(s);
    for(int i=n-1;i>=0;i--) extend(s[i]-'a');
    LL ans=0;
    for(int i=1;i<=n;i++) ans+=(LL)i*(n-1);
    printf("%lld\n",ans-2*solve());
    return 0;
}
View Code

另外转一下hzwer的SA解法:

--------------------------------------------------------------------------------------------------------------------------------------------蒟蒻与神犇的分界线--------------------------------------------

显然后缀数组不是正确姿势。。。

不过还是说说后缀数组的做法吧,bzoj总时限20s是能过的

SA+rmq求lcp应该烂大街了,这题还不用rmq。。。

首先求出h数组

考虑h[i]在哪些区间内会成为最小值,这个用两次单调栈很容易就能解决

还要处理一下由于h[i]可能相同造成的重复计数问题,具体看代码

code O(nlogn) 13592ms

#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 500005
#define inf 1000000000
#define pa pair<int,int>
#define ll long long 
using namespace std;
ll ans;
int n,k,p,q=1,top;
int v[N],a[N],h[N],sa[2][N],rk[2][N];
int st[N],l[N],r[N];
char ch[N];
void mul(int *sa,int *rk,int *SA,int *RK)
{
    for(int i=1;i<=n;i++)v[rk[sa[i]]]=i;
    for(int i=n;i;i--)
        if(sa[i]>k)
            SA[v[rk[sa[i]-k]]--]=sa[i]-k;
    for(int i=n-k+1;i<=n;i++)SA[v[rk[i]]--]=i;
    for(int i=1;i<=n;i++)
        RK[SA[i]]=RK[SA[i-1]]+(rk[SA[i-1]]!=rk[SA[i]]||rk[SA[i-1]+k]!=rk[SA[i]+k]);
}
void presa()
{
    for(int i=1;i<=n;i++)v[a[i]]++;
    for(int i=1;i<=30;i++)v[i]+=v[i-1];
    for(int i=1;i<=n;i++)sa[p][v[a[i]]--]=i;
    for(int i=1;i<=n;i++)
        rk[p][sa[p][i]]=rk[p][sa[p][i-1]]+(a[sa[p][i-1]]!=a[sa[p][i]]);
    for(k=1;k<n;k<<=1,swap(p,q))
        mul(sa[p],rk[p],sa[q],rk[q]);
    for(int k=0,i=1;i<=n;i++)
    {
        int j=sa[p][rk[p][i]-1];
        while(ch[j+k]==ch[i+k])k++;
        h[rk[p][i]]=k;if(k>0)k--;           
    }
}
void solve()
{
    for(int i=1;i<=n;i++)ans+=(ll)i*(n-1);
    h[0]=-inf;
    for(int i=1;i<=n;i++)
    {
        while(h[i]<=h[st[top]])top--;
        if(st[top]==0)l[i]=1;
        else l[i]=st[top]+1;
        st[++top]=i;
    }
    h[n+1]=-inf;top=0;st[0]=n+1;
    for(int i=n;i;i--)
    {
        while(h[i]<h[st[top]])top--;
        if(st[top]==n+1)r[i]=n;
        else r[i]=st[top]-1;
        st[++top]=i;
    }
    for(int i=1;i<=n;i++)
        ans-=2LL*(i-l[i]+1)*(r[i]-i+1)*h[i];
}
int main()
{
    scanf("%s",ch+1);
    n=strlen(ch+1);
    for(int i=1;i<=n;i++)a[i]=ch[i]-'a'+1;
    presa();
    solve();
    printf("%lld",ans);
    return 0;
}
View Code

 

 

转载于:https://www.cnblogs.com/wzj-is-a-juruo/p/4561157.html

内容概要:本文档详细介绍了一个基于MATLAB实现的跨尺度注意力机制(CSA)结合Transformer编码器的多变量时间序列预测项目。项目旨在精准捕捉多尺度时间序列特征,提升多变量时间序列的预测性能,降低模型计算复杂度与训练时间,增强模型的解释性和可视化能力。通过跨尺度注意力机制,模型可以同时捕获局部细节和全局趋势,显著提升预测精度和泛化能力。文档还探讨了项目面临的挑战,如多尺度特征融合、多变量复杂依赖关系、计算资源瓶颈等问题,并提出了相应的解决方案。此外,项目模型架构包括跨尺度注意力机制模块、Transformer编码器层和输出预测层,文档最后提供了部分MATLAB代码示例。 适合人群:具备一定编程基础,尤其是熟悉MATLAB和深度学习的科研人员、工程师和研究生。 使用场景及目标:①需要处理多变量、多尺度时间序列数据的研究和应用场景,如金融市场分析、气象预测、工业设备监控、交通流量预测等;②希望深入了解跨尺度注意力机制和Transformer编码器在时间序列预测中的应用;③希望通过MATLAB实现高效的多变量时间序列预测模型,提升预测精度和模型解释性。 其他说明:此项目不仅提供了一种新的技术路径来处理复杂的时间序列数据,还推动了多领域多变量时间序列应用的创新。文档中的代码示例和详细的模型描述有助于读者快速理解和复现该项目,促进学术和技术交流。建议读者在实践中结合自己的数据集进行调试和优化,以达到最佳的预测效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值