[JZOJ5129][SDOI省队集训2017]字符串
来源:互联网 发布:单片机晶振电容选择 编辑:程序博客网 时间:2024/06/07 11:26
题目大意
从n个字符串中依次选出一个子串拼接,求本质不同的数量。
SAM
我们尽量长化前面的。
于是倒着做,对每个串都要建SAM。
只需要处理开头是某个字符的方案数,SAM的一个节点没有该转移边即可。
大概就这样,懒得写清楚了。
#include<cstdio>#include<algorithm>#include<cstring>#define fo(i,a,b) for(i=a;i<=b;i++)#define fd(i,a,b) for(i=a;i>=b;i--)using namespace std;const int maxn=1000000+10,mo=1000000007;int g[maxn*2][26],step[maxn*2],fail[maxn*2],size[maxn*2],a[maxn],b[maxn];char s[maxn],h[maxn];int L[maxn],R[maxn];int f[26];int i,j,k,l,t,n,m,last,tot,top,ans,mx;void add(int x){ int p=last,np=++tot; step[np]=step[p]+1; while (p&&g[p][x]==0){ g[p][x]=np; p=fail[p]; } if (!p) fail[np]=1; else{ int q=g[p][x]; if (step[q]==step[p]+1) fail[np]=q; else{ int i,nq=++tot; fo(i,0,25) g[nq][i]=g[q][i]; fail[nq]=fail[q]; fail[q]=nq; fail[np]=nq; step[nq]=step[p]+1; while (p&&g[p][x]==q){ g[p][x]=nq; p=fail[p]; } } } last=np;}void work(){ int i; mx=0; fo(i,1,tot) mx=max(mx,step[i]); fo(i,0,mx) b[i]=0; fo(i,1,tot) b[step[i]]++; fo(i,1,mx) b[i]+=b[i-1]; fd(i,tot,1) a[b[step[i]]--]=i;}void clear(){ int i,j; fo(i,1,tot) fo(j,0,25) g[i][j]=0; fo(i,1,tot) size[i]=0; tot=0;}int main(){ freopen("str.in","r",stdin);freopen("str.out","w",stdout); scanf("%d",&n); top=1; fo(i,1,n){ L[i]=top; scanf("%s",h+1); m=strlen(h+1); fo(j,1,m) s[top++]=h[j]; R[i]=top-1; } fd(i,n,1){ last=tot=1; fo(j,L[i],R[i]) add(s[j]-'a'); work(); /*fd(j,tot,2){ fo(k,0,25) if (!g[a[j]][k]){ size[a[j]]+=f[k]; if (size[a[j]]>=mo) size[a[j]]-=mo; } size[fail[a[j]]]+=size[a[j]]; if (size[fail[a[j]]]>=mo) size[fail[a[j]]]-=mo; }*/ fd(j,tot,2){ size[a[j]]=1; fo(k,0,25) if (!g[a[j]][k]){ size[a[j]]+=f[k]; if (size[a[j]]>=mo) size[a[j]]-=mo; } else{ size[a[j]]+=size[g[a[j]][k]]; if (size[a[j]]>=mo) size[a[j]]-=mo; } } fo(j,0,25) if (g[1][j]) f[j]=size[g[1][j]]; clear(); } fo(i,0,25) (ans+=f[i])%=mo; ans++; ans%=mo; printf("%d\n",ans);}
阅读全文
0 0
- [JZOJ5129][SDOI省队集训2017]字符串
- [bzoj4927][SDOI省队集训2017]diyiti
- [bzoj4928][SDOI省队集训2017]dierti
- [bzoj4930][SDOI省队集训2017]棋盘
- [bzoj4931][SDOI省队集训2017]塔
- [JZOJ5133][SDOI省队集训2017]重建
- [JZOJ5136][SDOI省队集训2017]重排
- [JZOJ5131][SDOI省队集训2017]距离
- [JZOJ5130][51nod1446][SDOI省队集训2017]苹果树
- [JZOJ5132][SDOI省队集训2017]子序列
- [JZOJ5134][SDOI省队集训2017]三元组
- [JZOJ5135][SDOI省队集训2017]逆序对
- [JZOJ5137][SDOI省队集训2017][bzoj4842]养猫
- 【SDOI省队集训题】棋盘(最小费用流)
- 【SDOI省队集训题】pair(线段树+二分)
- SDOI省选总结
- SDOI 2017 Round1 题解
- 2017SDOI游记
- Cmake Practice
- 背包总结
- hdu4568
- vsftpd安装文档
- 《UNIX网络编程 卷1》 笔记: 多线程—web客户程序
- [JZOJ5129][SDOI省队集训2017]字符串
- 55 C语言条件运算符
- 如何查看JSP和Servlet版本
- Atom 安装
- Java Web 概论
- HDU 4572 Bottles Arrangement(数学推公式)——2013 ACM-ICPC长沙赛区全国邀请赛
- SpringBoot安装起步,第一个Demo
- 多线程-线程控制之礼让线程
- lintcode 463整数排序 lintcode 464整数排序II