题意

给定若干组由数字构成的字符串,求所有不重复子串的和(把他们看成十进制),答案mod(1e9+7)

题解:

类似后缀数组的做法,把字符串之间用':'连接,这里用':'是因为':'的ascii码恰好是9的下一个

然后建立后缀自动机。

之后把其实只要把其中的所有':'边删去,就可以进行转移了

如果x连向了y,边权是c,那么有转移

dp[y] += dp[x]*10 + c*sz[x]

所以只要拓扑排序一下就好

(写这题wa了好几次,主要是在删边建立新图的过程出了问题)

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
typedef long long LL;
int n = , len, st;
const int maxL = 2e6 + ;
const int MOD = 1e9 + ;
int maxlen[*maxL], minlen[*maxL], trans[*maxL][], slink[*maxL], col[*maxL];
LL in[*maxL], dp[*maxL], sz[*maxL];
int new_state(int _maxlen, int _minlen, int *_trans, int _slink){
maxlen[n] = _maxlen;
minlen[n] = _minlen;
for(int i = ; i < ; i++){
if(_trans == NULL)
trans[n][i] = -;
else
trans[n][i] = _trans[i];
}
slink[n] = _slink;
return n++;
} int add_char(char ch, int u){
int c = ch - '';
int z = new_state(maxlen[u]+, -, NULL, -);
int v = u;
while(v != - && trans[v][c] == -){
trans[v][c] = z;
v = slink[v];
}
if(v == -){
minlen[z] = ;
slink[z] = ;
return z;
}
int x = trans[v][c];
if(maxlen[v] + == maxlen[x]){
minlen[z] = maxlen[x] + ;
slink[z] = x;
return z;
}
int y = new_state(maxlen[v] + , -, trans[x], slink[x]);
slink[y] = slink[x];
minlen[x] = maxlen[y] + ;
slink[x] = y;
minlen[z] = maxlen[y] + ;
slink[z] = y;
int w = v;
while(w != - && trans[w][c] == x){
trans[w][c] = y;
w = slink[w];
}
minlen[y] = maxlen[slink[y]] + ;
return z;
} char str[maxL];
queue<int> Q;
int main()
{
freopen("a.txt", "r", stdin);
int N;
cin>>N;
st = new_state(, , NULL, -);
while(N--){
cin>>str;
int len = strlen(str);
for(int i = ; i < len; i++) {
st = add_char(str[i], st);
}
st = add_char(':', st);
}
Q.push(); col[] = ;
while(!Q.empty()){
int x = Q.front(); Q.pop();
for(int c = ; c < ; c++){
int y = trans[x][c];
if(y == -) continue;
if(!col[y]) Q.push(y); col[y] = ;
in[y]++;
}
}
Q.push(); sz[] = ;
while(!Q.empty()){
int x = Q.front(); Q.pop();
for(int c = ; c < ; c++){
int y = trans[x][c];
if(y == -) continue;
in[y]--;
if(in[y] == ) Q.push(y);
(sz[y] += sz[x]) %= MOD;
(dp[y] += dp[x]* + c*sz[x]) %= MOD;
}
}
LL ans = ;
/*
for(int i = 0; i < n; i++){
for(int c = 0; c < 10; c++){
if(trans[i][c] == -1) continue;
cout<<i<<" "<<trans[i][c]<<" "<<c<<endl;
}
}*/
//for(int i = 0; i < n; i++) cout<<dp[i]<<" "; cout<<endl;
for(int i = ; i < n; i++) (ans += dp[i]) %= MOD;
cout<<ans<<endl;
return ;
}

hihocoder 1457(后缀自动机+拓扑排序)的更多相关文章

  1. hihoCoder #1457 : 后缀自动机四·重复旋律7(后缀自动机 + 拓扑排序)

    http://hihocoder.com/problemset/problem/1457 val[i] 表示状态i所表示的所有字符串的十进制之和 ans= ∑ val[i]在后缀自动机上,从起始状态走 ...

  2. HIHOcoder 1457 后缀自动机四·重复旋律7

    思路 后缀自动机题目,题目本质上是要求求出所有不同的子串的和,SAM每个节点中存放的子串互不相同,所以对于每个节点的sum,可以发现是可以递推的,每个点对子节点贡献是sum[x]*10+c*sz[x] ...

  3. hihocoder 1457 后缀自动机四·重复旋律7 求不同子串的和

    描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 神奇的是小Hi发现了一部名字叫<十进制进行曲大全>的作品集,顾名思义,这部作品集里有许多作品 ...

  4. hihocoder 1457 后缀自动机四·重复旋律7 ( 多串连接处理技巧 )

    题目链接 分析 : 这道题对于单个串的用 SAM 然后想想怎么维护就行了 但是多个串下.可以先将所有的串用一个不在字符集( 这道题的字符集是 '0' ~ '9' ) 链接起来.建立后缀自动机之后 在统 ...

  5. hihoCoder.1457.后缀自动机四 重复旋律7(广义后缀自动机)

    题目链接 假设我们知道一个节点表示的子串的和sum,表示的串的个数cnt,那么它会给向数字x转移的节点p贡献 \(sum\times 10+c\times cnt\) 的和. 建广义SAM,按拓扑序正 ...

  6. hihoCoder #1465 : 后缀自动机五·重复旋律8

    http://hihocoder.com/problemset/problem/1465 求S的循环同构串在T中的出现次数 将串S变成SS 枚举SS的每个位置i,求出以i结尾的SS的子串 与 T的最长 ...

  7. HIHOcoder 1449 后缀自动机三·重复旋律6

    思路 显然endpos的大小就对应了对应子串的出现次数,所以快速求出endpos的大小,然后用它更新对应子串长度(minlen[i]~maxlen[i])的答案即可 endpos的大小可以拓扑排序求出 ...

  8. Luogu5284 十二省联考2019字符串问题(后缀树+拓扑排序)

    对反串建SAM弄出后缀树,每个b串通过倍增定位其在后缀树上对应的节点,根据其长度将节点拆开.然后每个a串也找到对应的节点,由该节点向表示a串的节点连边,再把所给的边连上跑拓扑排序即可. #includ ...

  9. hihoCoder #1445 : 后缀自动机二·重复旋律5

    #1445 : 后缀自动机二·重复旋律5 时间限制:10000ms 单点时限:2000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数 ...

随机推荐

  1. Java中事务总结详解(精华)

    1.什么是JAVA事务? 通常的观念认为,事务仅与数据库相关. 事务必须服从ISO/IEC所制定的ACID原则.ACID是原子性(atomicity).一致性(consistency).隔离性 (is ...

  2. html5 手风琴菜单

    因为项目需要,现在需要做个手风琴菜单,于是自己就瞎整了一下,所用只是less.js  javascript  jquery效果如图: 具体代码如下: <!DOCTYPE html> < ...

  3. vue过渡动画效果

    1 过渡基础 1.1 过渡的方式 Vue 在插入.更新或者移除 DOM 时,提供多种不同方式的应用过渡效果. 包括以下工具: 在 CSS 过渡和动画中自动应用 class 可以配合使用第三方 CSS ...

  4. 23种java设计模式之装饰者模式及动态代理

    设计模式不管对于何种语言都是存在的,这里介绍的是java的模式 装饰者模式是在二次开发中应用比较多的一款模式,当然了用反射也是可以实现的,今天介绍的是装饰模式,有兴趣的朋友可以自己去了解一下反射是怎么 ...

  5. python pandas库——pivot使用心得

    python pandas库——pivot使用心得 2017年12月14日 17:07:06 阅读数:364 最近在做基于python的数据分析工作,引用第三方数据分析库——pandas(versio ...

  6. python网络编程的坑(持续更新)

    初学python,踩了许多坑...每天都学一点吧..(大佬绕过) 1.session的用法: session是python requests库中的一个重要功能.session可以存储用户的数据并且存储 ...

  7. 001---Python简介

    编程语言: 机器语言 最底层,更容易被计算机识别,执行速度最快 复杂,开发效率低 汇编语言 比较底层,执行速度较快 同样复杂 高级语言 编译型语言:先编译,后执行.生成独立的可执行文件.是计算机可以理 ...

  8. JAVA 泛型方法<T>

    public static void main(String[] args) throws Exception { String[] arr = new String[]{"1", ...

  9. Spring事务:一种编程式事务,三种声明式事务

    事务隔离级别 隔离级别是指若干个并发的事务之间的隔离程度.TransactionDefinition 接口中定义了五个表示隔离级别的常量: TransactionDefinition.ISOLATIO ...

  10. java反射操作类方法与属性

    package com.fanshe.test; public class User { private int age; private String email; private String u ...