「2017 山东一轮集训 Day5」字符串
比较神仙的操作啊
首先先考虑一个串的做法,我们有两种:SA或SAM,其中SAM又有两种,拓扑图上的\(dp\)和\(parent\)上随便统计一下
显然这道题\(SA\)和\(parent\)树都不是很好搞啊,考虑求一下拓扑图上的路径总数
我们先对每一个串单独建一个\(SAM\),每一个\(SAM\)都得到了一张\(DAG\)
对于一个节点\(x\)如果发现这个节点没有代表某个字母\(c\)的转移边,我们就找到这个串之后的一个有\(c\)的串,让\(x\)向那一张\(DAG\)的起始节点\(c\)转移边指向的点连边
现在我们建出来的\(DAG\)就非常牛逼了,如果发现想走某一条转移边而没有办法走的时候,它会自动跳到下一个字符串上去,我们在这张\(DAG\)上求一下路径总数就是答案了
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define re register
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read() {
char c=getchar();int x=0;while(c<'0'||x>'9') c=getchar();
while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
}
const int mod=1e9+7;
const int maxn=3e6+5;
int cnt,lst,n,tot,ans;
char S[maxn>>1];
int son[maxn][26],fa[maxn],len[maxn],rt[maxn>>1],r[maxn],q[maxn],dp[maxn];
int st[26][maxn>>1],top[26],now[26],ed[maxn>>1];
inline void ins(int c,int o) {
int f=lst,p=++cnt;lst=p;
len[p]=len[f]+1;
while(f&&!son[f][c]) son[f][c]=p,f=fa[f];
if(!f) {fa[p]=rt[o];return;}
int x=son[f][c];
if(len[f]+1==len[x]) {fa[p]=x;return;}
int y=++cnt;
len[y]=len[f]+1,fa[y]=fa[x],fa[x]=fa[p]=y;
for(re int i=0;i<26;i++) son[y][i]=son[x][i];
while(f&&son[f][c]==x) son[f][c]=y,f=fa[f];
}
int main() {
scanf("%d",&n);
for(re int i=1;i<=n;i++) {
scanf("%s",S+1);
ed[i-1]=cnt;rt[i]=++cnt;lst=cnt;
int len=strlen(S+1);
for(re int j=1;j<=len;j++)
ins(S[j]-'a',i);
}
ed[n]=cnt;
for(re int i=2;i<=n;i++)
for(re int j=0;j<26;j++)
if(son[rt[i]][j]) st[j][++top[j]]=i;
for(re int j=0;j<26;j++) now[j]=1;
for(re int i=1;i<n;i++) {
for(re int j=0;j<26;j++)
while(now[j]<=top[j]&&st[j][now[j]]<=i) now[j]++;
for(re int j=rt[i];j<=ed[i];j++)
for(re int k=0;k<26;k++)
if(!son[j][k]&&now[k]<=top[k])
son[j][k]=son[rt[st[k][now[k]]]][k];
}
for(re int i=1;i<=cnt;i++)
for(re int j=0;j<26;j++)
if(son[i][j]) r[son[i][j]]++;
for(re int i=1;i<=cnt;i++) if(!r[i]) q[++tot]=i;
dp[1]=1;
for(re int i=1;i<=tot;i++) {
int x=q[i];
for(re int j=0;j<26;j++) {
if(!son[x][j]) continue;
r[son[x][j]]--;
dp[son[x][j]]=(dp[son[x][j]]+dp[x])%mod;
if(!r[son[x][j]]) q[++tot]=son[x][j];
}
}
for(re int i=1;i<=cnt;i++) ans=(ans+dp[i])%mod;
printf("%d\n",ans);
return 0;
}
「2017 山东一轮集训 Day5」字符串的更多相关文章
- 「2017 山东一轮集训 Day5」字符串 (后缀自动机, 拓扑排序)
/** 首先通过SAM求出每个串本质不同的子串 然后发现转移不好处理整体的本质不同 形如串A可能状态有a,b,ab,空,串B可能状态有b,空两种, 那么我们需要处理ab + 空 和 a + b的情况 ...
- LOJ6071. 「2017 山东一轮集训 Day5」字符串 [SAM]
LOJ 思路 这种计数题显然是要先把每一个合法的串用唯一的方法表示出来.(我连这都没想到真是无可救药了) 如何唯一?容易想到把前缀尽可能多地在第一个串填掉,然后填第二个,第三个-- 如何做到这样?可以 ...
- Loj #6073.「2017 山东一轮集训 Day5」距离
Loj #6073.「2017 山东一轮集训 Day5」距离 Description 给定一棵 \(n\) 个点的边带权的树,以及一个排列$ p\(,有\)q $个询问,给定点 \(u, v, k\) ...
- 「2017 山东一轮集训 Day5」苹果树
「2017 山东一轮集训 Day5」苹果树 \(n\leq 40\) 折半搜索+矩阵树定理. 没有想到折半搜索. 首先我们先枚举\(k\)个好点,我们让它们一定没有用的.要满足这个条件就要使它只能和坏 ...
- loj#6073. 「2017 山东一轮集训 Day5」距离(树链剖分 主席树)
题意 题目链接 Sol 首先对询问差分一下,我们就只需要统计\(u, v, lca(u, v), fa[lca(u, v)]\)到根的路径的贡献. 再把每个点与\(k\)的lca的距离差分一下,则只需 ...
- loj#6073. 「2017 山东一轮集训 Day5」距离(费用流)
题意 题目链接 Sol 我们可以把图行列拆开,同时对于行/列拆成很多个联通块,然后考虑每个点所在的行联通块/列联通块的贡献. 可以这样建边 从S向每个行联通块连联通块大小条边,每条边的容量为1,费用为 ...
- 「2017 山东一轮集训 Day5」距离
/* 写完开店再写这个题目顿时神清气爽, 腰也不疼了, 眼也不花了 首先考虑将询问拆开, 就是查询一些到根的链和点k的关系 根据我们开店的结论, 一个点集到一个定点的距离和可以分三部分算 那么就很简单 ...
- 题解 「2017 山东一轮集训 Day5」苹果树
题目传送门 题目大意 给出一个 \(n\) 个点的图,每个点都有一个权值 \(f_i\) ,如果 \(f_i=-1\) 表示 \(i\) 这个点是坏的.定义一个点是有用的当且仅当它不是坏的,并且它连的 ...
- Loj #6069. 「2017 山东一轮集训 Day4」塔
Loj #6069. 「2017 山东一轮集训 Day4」塔 题目描述 现在有一条 $ [1, l] $ 的数轴,要在上面造 $ n $ 座塔,每座塔的坐标要两两不同,且为整点. 塔有编号,且每座塔都 ...
随机推荐
- css布局记录之双飞翼布局、圣杯布局
双飞翼布局和圣杯布局是比较常用的布局方式,都是为了实现一行三列,并且两侧列固定宽度,中间列宽度自适应的效果:直接上代码记录下: <!DOCTYPE html> <html lang= ...
- Android - fragment Manager
fragment基本使用: http://www.cnblogs.com/qlky/p/5415679.html Fragmeng优点 Fragment可以使你能够将activity分离成多个可重用的 ...
- Java虚拟机 - Javac编译与JIT编译
[深入Java虚拟机]之七:Javac编译与JIT编译 编译过程 不论是物理机还是虚拟机,大部分的程序代码从开始编译到最终转化成物理机的目标代码或虚拟机能执行的指令集之前,都会按照如下图所示的各个步骤 ...
- 在微信小程序中引入 Iconfont 阿里巴巴图标库
小程序的代码包不能超过4M,为了压缩代码包的大小,可以通过第三方链接引入图标资源 Iconfont 无疑是最常用的第三方图标库,这里介绍一下在微信小程序引入 Iconfont 的方法 一.下载图标 首 ...
- eclipse搭建hibernate环境
一.打开eclipse,help=>Install New Software 输入:http://download.jboss.org/jbosstools/updates/stable/kep ...
- Difference between nn.softmax & softmax_cross_entropy_with_logits & softmax_cross_entropy_with_logits_v2
nn.softmax 和 softmax_cross_entropy_with_logits 和 softmax_cross_entropy_with_logits_v2 的区别 You have ...
- Python 排错UnicodeEncodeError 'ascii' codec can't encode character 错误解决方法
Python UnicodeEncodeError 'ascii' codec can't encode character 错误解决方法 by:授客 QQ:1033553122 错误描述: py ...
- CountDownTimer 源码分析
倒计时的功能,比如说:发送短信验证码倒计时. public class CountDownTimerActivity extends Activity { private Button mSend; ...
- JSP源码、改写Servlet为JSP、查看转译成为Servlet的文件、JSP字符编码设置
概述 在Servlet中编写HTML太麻烦了,应该使用JSP.JSP中可以直接编写HTML,使用指示.声明.脚本(scriptlet)等元素来堆砌各种功能,但JSP最后还是会被容器转译为Servlet ...
- Expo大作战(十九)--expo打包后,发布分用程序到商店的注意事项
简要:本系列文章讲会对expo进行全面的介绍,本人从2017年6月份接触expo以来,对expo的研究断断续续,一路走来将近10个月,废话不多说,接下来你看到内容,讲全部来与官网 我猜去全部机翻+个人 ...