字符串 后缀自动机+动态规划
来源:互联网 发布:数据库运维工作内容 编辑:程序博客网 时间:2024/06/06 07:00
题意
分析
考虑如果现在有一个串T,我们要如何去判断T是否能被构造。贪心地想,肯定是先在第一个串里面找到最长的一个子串,满足该子串是T的前缀,然后再到第二个串找,如此类推。
如果只有一个串的话,找本质不同的子串的其中一种方法就是先建出sam,然后在sam的DAG上dp一下求出从原点到每个点有多少种不同的路径。
拓展到多个串,我们可以先对每个串建出后缀自动机,然后从最后一个串往前dp,每一个串的sam都按照逆拓扑序来dp。设f[u]表示从u这个节点往后走有多少种不同的方案。若u有连出去字符x的边,设连到v,则f[u]+=f[v]。否则,找到后面第一个存在字符x的串,设这个串的原点连出去字符x的边会走到w,则f[u]+=f[w]。
最后第一个串的原点,设为s,f[s]则是答案。
代码
#include<iostream> #include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<queue>using namespace std;const int N=3000005;const int MOD=1000000007;int n,cnt,last,ch[N][26],f[N],mx[N],fa[N],numl[N],numr[N],nx[26],a1,a[N],d[N];char s[N];queue<int> que;void ins(int x,int y){ int p,q,np,nq; p=last;last=np=++cnt;mx[np]=mx[p]+1; for (;!ch[p][x]&&p;p=fa[p]) ch[p][x]=np; if (!p) fa[np]=y; else { q=ch[p][x]; if (mx[q]==mx[p]+1) fa[np]=q; else { nq=++cnt;mx[nq]=mx[p]+1; memcpy(ch[nq],ch[q],sizeof(ch[q])); fa[nq]=fa[q]; fa[q]=fa[np]=nq; for (;ch[p][x]==q;p=fa[p]) ch[p][x]=nq; } }}void topsort(int l,int r){ for (int i=l;i<=r;i++) for (int j=0;j<26;j++) if (ch[i][j]) d[ch[i][j]]++; for (int i=l;i<=r;i++) if (!d[i]) que.push(i); a1=0; while (!que.empty()) { int u=que.front();que.pop();a[++a1]=u; for (int i=0;i<26;i++) if (ch[u][i]) { d[ch[u][i]]--; if (!d[ch[u][i]]) que.push(ch[u][i]); } }}int main(){ freopen("str.in","r",stdin);freopen("str.out","w",stdout); scanf("%d",&n); for (int i=1;i<=n;i++) { scanf("%s",s); last=++cnt;numl[i]=last; int len=strlen(s); for (int j=0;j<len;j++) ins(s[j]-'a',numl[i]); numr[i]=cnt; } for (int i=n;i>=1;i--) { topsort(numl[i],numr[i]); for (int j=a1;j>=1;j--) { int x=a[j]; f[x]=1; for (int k=0;k<26;k++) if (ch[x][k]) (f[x]+=f[ch[x][k]])%=MOD; else if (nx[k]) (f[x]+=f[ch[numl[nx[k]]][k]])%=MOD; } for (int k=0;k<26;k++) if (ch[numl[i]][k]) nx[k]=i; } printf("%d",f[1]); return 0;}
阅读全文
0 0
- 字符串 后缀自动机+动态规划
- [多校][HDU5343]MZL's Circle Zhou后缀自动机+动态规划
- 字符串专题:后缀自动机
- 【字符串】后缀自动机小结
- 动态规划和字符串匹配(KMP、AC自动机)
- 【字符串新武器】后缀自动机
- 【字符串新武器】后缀自动机
- Bzoj3473:字符串:广义后缀自动机
- pku1625 AC自动机,动态规划
- BZOJ 2555: SubString 动态树+后缀自动机
- bzoj2555: SubString(后缀自动机+动态树)
- 字符串 KMP Trie AC自动机 后缀数组
- 字符串模板总结(五):后缀自动机
- 字符串后缀自动机:Directed Acyclic Word Graph
- 字符串匹配:从后缀自动机到KMP
- [BZOJ3473][后缀自动机][启发式合并]字符串
- bzoj 3473: 字符串 广义后缀自动机
- 4556: [Tjoi2016&Heoi2016]字符串 后缀自动机 详细
- 个人工作日记
- 深度学习笔记一
- Git SSH Key 生成
- MAC 配置 Java 环境变量
- Handing time
- 字符串 后缀自动机+动态规划
- 1064: [Noi2008]假面舞会
- 关闭Android手机dm-encrpyt
- android之存储篇_SQLite数据库_让你彻底学会SQLite的使用
- Java代码生成excel文件下载
- Java文件操作①——XML文件的读取
- java-多态
- 字节流、字符串、16进制字符串转换__Java(转)
- spring