题意

给定若干组由数字构成的字符串,求所有不重复子串的和(把他们看成十进制),答案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. 在Liunx Mint下无法切换到root用户

    提示 su: Authentication failure 以ubuntu的mint root用户默认是也是禁止的 需要手动打开才行 a)root启用 执行下面的操作:1.先解除root锁定,为roo ...

  2. css实现下拉菜单功能(多中实现方式即原理)

    引导思路: 1.需要用到的元素:position hover (z-index)  或(overflow)或(display)等等. 关键点就是div的溢出部分的处理. 2.实现过程: 2.1:就是要 ...

  3. maven-生命周期与插件

    Maven的生命周期是抽象的,具体的操作由插件实现,类似于java的模板设计模式. 1.生命周期 认识生命周期 maven有clean.default.site三种生命周期,每种生命周期都包含一些阶段 ...

  4. C#正则表达式Regex类的使用

    C#中为正则表达式的使用提供了非常强大的功能,这就是Regex类.这个包包含于System.Text.RegularExpressions命名空间下面,而这个命名空间所在DLL基本上在所有的项目模板中 ...

  5. git上下载的thinkphp框架报错解决方法

    ​ git上下载的thinkphp5框架使用.gitignore没上传依赖,需要通过composer进行下载依赖,使用composer install或者composer update即可解决.

  6. ubuntu 18 lnmp

    1安装Nginx sudo apt-get install nginx 2安装PHP sudo apt- php7.-fpm 3安装mysql sudo apt-get install mysql 启 ...

  7. 07 json与os模块(进阶)

    json和os模块 阶段一 .数据交换 1.json的基本介绍 JSON全名是JavaScript Object Notation(即:JavaScript对象标记)它是JavaScript的子集. ...

  8. 多线程编程之Apue3rd_Chapter11之互斥锁_读写锁_自旋锁

    学习了apue3rd的第11章,主要讲的是多线程编程.因为线程共享进程的资源比如堆和全局变量,多线程编程最重要的是,使用各种锁进行线程同步. 线程编程首先要学习的三个函数如下: #include &l ...

  9. 配置vue-yarm-PM2工具环境

    步骤: 第一步:安装yarn 参考网址:https://yarn.bootcss.com/docs/install.html#linux-tab a.用pm2启动已创建的server.js   #pm ...

  10. HDU 5530:Pipes Selection

    题意: 给定长度为\(L\),元素总和为\(S\)的非负整数序列\(A\),对于每一个\(1 \leq i \leq S\),求出:所有满足\(\sum_{j=l}^rA_j=i\)的二元组\((l, ...