4516: [Sdoi2016]生成魔咒
4516: [Sdoi2016]生成魔咒
题意:
求本质不同的子串。
分析:
后缀数组或者SAM都可以。
考虑SAM中每个点的可以表示的子串是一个区间min(S)~max(S),把每个点的这个区间加起来即可。
字符集有点大,可以用map。
代码:
#include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> #include<cctype> #include<set> #include<queue> #include<vector> #include<map> using namespace std; typedef long long LL; inline int read() { int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f; } const int N = 200005; map<int,int> ch[N]; int fa[N], len[N], Index = 1, Last = 1; LL Ans; void extend(int c) { int np = ++Index, p = Last; len[np] = len[p] + 1; for (; p && ch[p].find(c) == ch[p].end(); p = fa[p]) ch[p][c] = np; if (!p) fa[np] = 1; else { int Q = ch[p][c]; if (len[Q] == len[p] + 1) fa[np] = Q; else { int NQ = ++Index; fa[NQ] = fa[Q]; ch[NQ] = ch[Q]; len[NQ] = len[p] + 1; fa[Q] = fa[np] = NQ; for (; p && ch[p].find(c) != ch[p].end() && ch[p][c] == Q; p = fa[p]) ch[p][c] = NQ; } } Last = np; Ans += len[np] - len[fa[np]]; // max(np)=len[np], min(np)=len[fa[p]] + 1 printf("%lld\n", Ans); } int main() { int n = read(); for (int i = 1; i <= n; ++i) { int x = read(); extend(x); } return 0; }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core内存结构体系(Windows环境)底层原理浅谈
· C# 深度学习:对抗生成网络(GAN)训练头像生成模型
· .NET 适配 HarmonyOS 进展
· .NET 进程 stackoverflow异常后,还可以接收 TCP 连接请求吗?
· SQL Server统计信息更新会被阻塞或引起会话阻塞吗?
· 传国玉玺易主,ai.com竟然跳转到国产AI
· 本地部署 DeepSeek:小白也能轻松搞定!
· 自己如何在本地电脑从零搭建DeepSeek!手把手教学,快来看看! (建议收藏)
· 我们是如何解决abp身上的几个痛点
· 普通人也能轻松掌握的20个DeepSeek高频提示词(2025版)