http://www.elijahqi.win/archives/3945
今天研究一天怎么构造始终想不明白 看到这篇blog之后顿悟

为了帮助其他人避免像蒟蒻我一样 想不明白感到难过

于是随便写一写

要是有错误 qwq麻烦指出

(emm退役之后不知道还会不会上blog)

https://www.cnblogs.com/hehe54321/p/8694839.html

看上面两张图中,上面的那张图:后缀链接对应的后缀树上的边是:

5->S===>b,4->5===>baa,3->5===>aa,2->1===>a,1->s===>a,也就是后缀链接起点能接受的所有长度的串,按长度从小到大排,各取第一个字符组成的串

后缀树的根就是S

从某一节点沿着后缀链接走到S,记录下经过所有边代表的串,翻转序列,连成一个字符串,然后翻转整个字符串,就是该节点在后缀自动机上能接受的最长串

某一节点能接受的最长串为S,则该节点能接受的所有串都是S的后缀,往后缀链接跳一步到的节点能接受的串则也是S的

板子

知道一个性质 sam上的parent树就是反串的后缀树

那么我们要求后缀树的时候把原串反过来建SAM即可 这样保证状态节点数什么的都是线性o(n)

那么我们考虑 后缀自动机 par树的含义是 针对我这个节点所能表示的串的最长后缀的位置

我们参照这个图 反串建立后缀自动机的时候我们尝试沿着par树行走 发现反串的par树其实相当于原串的一些前缀 然后每次跳par树的时候都相当于在找一个后缀的前缀

然后那么如果要看后缀树上表示的边到底压缩了哪些字母我们可以考虑 在后缀自动机上用我当前的节点能表示的最长串-fa[当前节点]表示的最长串 然后将其反过来就是后缀树上压缩的边了
贴一道题:

Lyra 是一个灵巧的女孩子,她特别喜欢玩一种叫“石头剪刀布”的游戏,在这个游戏中,每回合双方同时打出一种手势,为石头(r),剪刀(s),布(p)之一,规定石头打败剪刀,剪刀打败布,布打败石头,若手势一样则视为平局。

虽然 Lyra 是一个灵巧的女孩子,她发现她依然赢不了 Evan,潜心研究多日 Evan 的策略后,发现在第二天的 n

n

轮游戏中,Evan 一定以某种固定策略出手势。

这个固定策略(一个长度为 n

n

的由 r,s,p

r,s,p

组成的字符串)就藏在 Evan 的电脑里,被 Evan 加密存储。Evan 的加密方式很奇怪,他先选取一个特定的 d

d

,然后把整个字符串循环右移 d

d

个位置。

Lyra 拿到了加密后的策略串,她想在第二天的石头剪刀布比赛中大败 Evan,注意 Lyra 的策略不一定必须是开始前固定的,可以根据前若干回合的结果修正之后的策略。

在这场石头剪刀布大赛中,对于第 i

i

个回合,获胜可以获得 wi

wi

分,平局获得 di

di

分,而失败获得 0

0

分。Lyra 想知道自己采取最优策略的话,最坏情况下至少从这 n

n

个回合中获得多少分。

输入格式
第一行三个正整数 n

n

表示回合数。

第二行一个长度为 n

n

的字符串 S

S

表示 Evan 的序列的某个轮换。

接下来 n

n

行每行两个整数 wi,di

wi,di

,表示获胜得分,平局得分。

输出格式
一行一个正整数表示 Lyra 至少获得的分数。

样例输入输出
样例输入1
5
rrsrr
3 1
3 1
3 1
3 1
3 1
样例输出1
12
样例输入2
6
rsprsp
3 1
3 1
3 1
3 1
3 1
3 1
样例输出2
15
在苏州训练的时候lzz的一道题 暴力做法就是暴力建出后缀trie之后在trie上dp 对于题意我是理解了很久

其实是在我出的所有方案中 每种方案对应一种最坏的情况 然后我选择这三种情况中最好的一种情况

那么 将串复制一遍 然后在反过来建sam就可以得到后缀树 然后后缀树就是精简之后的后缀trie所以我们在后缀trie上dp可以得到同样的效果 因为这题我们边上只有一种对应的情况所以我们总能赢所以预处理一下能赢的前缀和 到时候减去即可 关于如何确定这个被压缩起来的是哪个我们可以考虑我们现在在sam上的len其实表示的是我原串的一个前缀的长度 所以假如我知道一个节点对应原串的位置我就可以知道他转移到下一个节点是哪里 然后我用我当前位置+下一个节点最长长度-我的最长长度就得到我这条边压缩起来的大小是多少 另外被压缩的字符 恰好就是原串这个对应位置的一个串

#include<bits/stdc++.h>
#define ll long long
using namespace std;
inline char gc(){static char now[1<<16],*S,*T;if(T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}return *S++;
}
inline int read(){int x=0,f=1;char ch=gc();while(!isdigit(ch)) {if (ch=='-') f=-1;ch=gc();}while(isdigit(ch)) x=x*10+ch-'0',ch=gc();return x*f;
}
const int N=4e5+20;
const ll inf=1ll<<60;
int s[N],last=1,cnt=1,root=1,ch[N][3],len[N],fa[N],p[N];
ll dp[N],pre[N];int n,w[N],d[N],trans[N][3];bool visit[N];
inline void reads(){char ch=gc();while(ch!='r'&&ch!='p'&&ch!='s') ch=gc();int tot=0;while(ch=='r'||ch=='p'||ch=='s') {++tot;if (ch=='r') s[tot]=0;else if (ch=='s') s[tot]=1;else s[tot]=2;ch=gc();}
}
inline void insert1(int x){int p=last,np=++cnt;len[np]=len[p]+1;for (;p&&!ch[p][x];p=fa[p]) ch[p][x]=np;if (!p) fa[np]=root;else{int q=ch[p][x];if (len[p]+1==len[q]) fa[np]=q;else{    int nq=++cnt;fa[nq]=fa[q];len[nq]=len[p]+1;memcpy(ch[nq],ch[q],sizeof(ch[q]));fa[np]=fa[q]=nq;for (;p&&ch[p][x]==q;p=fa[p]) ch[p][x]=nq;}}last=np;
}
inline void init(){for (int i=1;i<=n<<1;++i){int now=p[i];while(!visit[now]){int f=fa[now];visit[now]=1;trans[f][s[i+len[f]]]=now;now=f;}}for (int i=1;i<=n;++i) pre[i]=pre[i-1]+w[i];
}
inline void dfs(int x){if(visit[x]) return;visit[x]=1;for (int i=0;i<=2;++i){ll mn=inf;for (int j=0;j<=2;++j){int y=trans[x][j];if (!y) continue;ll sum=pre[min(n,len[y])]-pre[len[x]+1];if(len[y]<n) dfs(y),sum+=dp[y];if((i+1)%3==j) sum+=w[len[x]+1];if(i==j) sum+=d[len[x]+1];mn=min(mn,sum);}dp[x]=max(dp[x],mn);}
}
int main(){freopen("d.in","r",stdin);n=read();reads();for (int i=1;i<=n;++i) w[i]=read(),d[i]=read();for (int i=n;i;--i) insert1(s[i]),p[i+n]=last;for (int i=n;i;--i) insert1(s[i]),p[i]=last,s[i+n]=s[i];visit[1]=1;init();memset(visit,0,sizeof(visit));dfs(1);printf("%lld\n",dp[1]);return 0;
}

后缀自动机构造后缀树相关推荐

  1. 使用后缀自动机求后缀数组

    倒序建立后缀自动机的fail树就是后缀树,dfs后缀树得到后缀数组 #include <bits/stdc++.h> using namespace std;int last,dis[20 ...

  2. c语言后缀表达式构造二叉树,C ++程序为后缀表达式构造表达式树

    表达式树基本上是用于表示表达式的二叉树.在表达式树中,节点对应于运算符,每个叶节点对应于操作数.这是一个C ++程序,用于按顺序,前顺序和后顺序遍历为后缀表达式构造一个表达式树. 算法Begin Fu ...

  3. UOJ #395 BZOJ 5417 Luogu P4770 [NOI2018]你的名字 (后缀自动机、线段树合并)

    NOI2019考前做NOI2018题.. 题目链接: (bzoj) https://www.lydsy.com/JudgeOnline/problem.php?id=5417 (luogu) http ...

  4. BZOJ3998: [TJOI2015]弦论(后缀自动机,Parent树)

    Description 对于一个给定长度为N的字符串,求它的第K小子串是什么. Input 第一行是一个仅由小写英文字母构成的字符串S 第二行为两个整数T和K,T为0则表示不同位置的相同子串算作一个. ...

  5. 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数

    目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...

  6. 2019牛客暑期多校训练营(第四场)I - String (后缀自动机+回文树)

    题目链接 题意 给一个字符串,求字符串子串的最大集合,集合中字符串互不相等,相等的定义为:a≠ba =\not ba≠​b 而且 a≠rev(b)a =\not rev(b)a≠​rev(b) ...

  7. 后缀自动机(SAM)构造实现过程演示+习题集锦

    文章目录 后缀自动机 算法实现过程 模板 习题 洛谷后缀自动机模板题 品酒大会 [HEOI2015]最短不公共子串 字符串 蒟蒻写这篇blogblogblog主要是存一下,后缀自动机的详细搭建过程,方 ...

  8. @总结 - 6@ 后缀自动机

    目录 @0 - 参考资料@ @0.5 - 引言@ @1 - what is it?@ @自动机@ @DAWG@ @终点集合 end-pos@ @后缀链接 与 parent 树@ @2 - how to ...

  9. 后缀自动机(SAM)讲解 + Luogu p3804【模板】后缀自动机 (SAM)

    本文求节点子串长度最小值有点问题,现已修改. SAM 后缀自动机可以存储某一个字符串的所有子串. 一.概念 下图是一个 字符串 "aababa" 的 后缀自动机. 上图中的 黑色边 ...

最新文章

  1. [译] MDC-101 Flutter:Material Components(MDC)基础(Flutter)
  2. python操作系统-python获取操作系统平台、版本及架构
  3. UISegmentedControl的详细使用
  4. 数据治理的理论实践与发展趋势
  5. Git安装以及操作过程
  6. 一天搞定HTML----标签语义化04
  7. how to change logo in ae template
  8. 机器学习-Kmeans聚类
  9. 4.2 神经网络算法代码实现
  10. 用dotnet自带的mail类发邮件出现的问题
  11. 我又发现一个直接就能安装中文小红帽的方法
  12. Active Directory 灾难恢复
  13. 关于Spring Cloud Config服务器介绍
  14. 契税申报期限_纳税申报的5个小常识,不知道的不是合格的财务人!
  15. java txt 分段读取_Java 读取TXT文件的多种方式
  16. 让 Flutter 在鸿蒙系统上跑起来
  17. Mobaxterm 中文输入Backspace按键问题
  18. 带宽、传输速率、吞吐量的概念区别
  19. MATLAB导入EXCEL表格数据画散点图
  20. 人力资源管理计算机基础,人力资源管理-专-李佑强-计算机应用基础实践报告

热门文章

  1. 我把面试 ThreadLocal 能问的,都写了
  2. [Javascript学习笔记]JS变量不声明也能使用,直接天下无敌!
  3. 工业机器人入门z50的含义_工业机器人实操与应用技巧第版.PDF
  4. postgresql 数据库导出和导入
  5. IDEA刷新项目目录
  6. 从sockaddr结构获取IP和端口
  7. 直播成电商标配,网红与KOL搭配效果更佳?
  8. python url解码_对python中url参数编码与解码的实例详解
  9. git 撤销刚才的rebase_撤消git rebase
  10. Linux系统漏洞复现分析,Linux环境下常见漏洞利用技术