题意:给出n个数字,数字很长,用字符串读入,长度总和为10^5。求这n个字符串的所有子串(不重复)的和取模2012 。

例如字符串101,和就是1+10+101=112。

题解:

就是求不同的子串连成一个数。
sam的拓扑序真的很有用!按拓扑序可以保证能转移到当前x的节点都在之前被更新了。
每个节点x维护cnt表示root到x的方案数,sum表示以x为结尾的子串和。
找拓扑序有两种方法:1.拓扑排序一样bfs(O(n)) 2.按照step[x]排序(若x有个孩子是y,step[x]<=step[y](O(nlogn))
按照拓扑序for一遍,对于x,它的孩子y,cnt[y]+=cnt[x],sum[y]+=sum[x]*10+cnt[x]*(y所代表的数字)。
不能有前缀0----->根节点不走0孩子。
节点数开了10^6才AC。tell me why?!

打了两种求拓扑序的方法。

贴一下代码。

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<queue>
#include<ctime>
#include<algorithm>
using namespace std; const int N=*,Mod=;
char s[N];
int n,sl,cl,ans,tot,last;
int son[N][],pre[N],step[N],sum[N],in[N],cnt[N],c[N];
bool vis[N];
queue<int> Q; int add_node(int x)
{
step[++tot]=x;
return tot;
} void extend(int ch)
{
int p=last,np=add_node(step[last]+);
while(p && !son[p][ch]) son[p][ch]=np,in[np]++,p=pre[p];
if(!p) pre[np]=;
else
{
int q=son[p][ch];
if(step[q]==step[p]+) pre[np]=q;
else
{
int nq=add_node(step[p]+);
memcpy(son[nq],son[q],sizeof(son[q]));
for(int i=;i<=;i++)
if(son[q][i]) in[son[q][i]]++;
pre[nq]=pre[q];
pre[np]=pre[q]=nq;
while(son[p][ch]==q) in[q]--,in[nq]++,son[p][ch]=nq,p=pre[p];
}
}
last=np;
} void find_tp_1()
{
for(int i=;i<=tot;i++)
{
if(in[i]==)
{
for(int j=;j<=;j++)
{
int y=son[i][j];
if(!y) continue;
in[y]--;
}
}
}
while(!Q.empty()) Q.pop();
Q.push();vis[]=;cl=;
while(!Q.empty())
{
int x=Q.front();vis[x]=;c[++cl]=x;Q.pop();
for(int i=;i<=;i++)
{
int y=son[x][i];
if(!y) continue;
in[y]--;
if(!in[y] && !vis[y]) vis[y]=,Q.push(y);
}
}
} bool cmp(int x,int y){return step[x]<step[y];}
void find_tp_2()
{
cl=;
for(int i=;i<=tot;i++)
{
if(in[i] || i==) c[++cl]=i;
}
sort(c+,c++cl,cmp);
} void solve()
{
cnt[]=;
for(int i=;i<=cl;i++)
{
int x=c[i];
for(int j=;j<=;j++)
{
int y=son[x][j];
if(!y || (x== && j==)) continue;
cnt[y]=(cnt[y]+cnt[x])%Mod;
sum[y]=(sum[y]+(sum[x]*)%Mod+(j*cnt[x])%Mod)%Mod;
}
}
} int main()
{
freopen("a.in","r",stdin);
// freopen("me.out","w",stdout);
while(scanf("%d",&n)!=EOF)
{
memset(son,,sizeof(son));
memset(step,,sizeof(step));
memset(pre,,sizeof(pre));
memset(in,,sizeof(in));
memset(cnt,,sizeof(cnt));
memset(sum,,sizeof(sum));
tot=;add_node();last=;
for(int i=;i<=n;i++)
{
scanf("%s",s+);
sl=strlen(s+);
last=;
for(int j=;j<=sl;j++) extend(s[j]-'');
}
find_tp_1();//找拓扑序方法一 : bfs=拓扑排序
// find_tp_2();//方法二:直接对step[x]进行排序
solve();
ans=;
for(int i=;i<=tot;i++) ans=(ans+sum[i])%Mod;
printf("%d\n",ans);
// cout<<"Time Used : "<<(double)clock()/CLOCKS_PER_SEC<<" s."<<endl;
}
return ;
}

【hdu4436/LA6387-str2int】sam处理不同子串的更多相关文章

  1. 后缀自动机(SAM)

    *在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符 ...

  2. 后缀自己主动机(SAM)学习指南

    *在学习后缀自己主动机之前须要熟练掌握WA自己主动机.RE自己主动机与TLE自己主动机* 什么是后缀自己主动机 后缀自己主动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂 ...

  3. 【算法】后缀自动机(SAM) 例题

    算法介绍见:http://www.cnblogs.com/Sakits/p/8232402.html 广义SAM资料:https://www.cnblogs.com/phile/p/4511571.h ...

  4. hihoCoder 后缀自动机三·重复旋律6

    后缀自动机三·重复旋律6 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi ...

  5. BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡

    3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1017  Solved: 599[Submit][S ...

  6. 51nod1647 小Z的trie

    题意:给你n个字符串,m次查询,每次问你第p个字符串的s到t的字符串在n个字符串建成的字典树上出现了多少次 题解:先建出字典树,在字典树上拓展sam,记录每个子串的出现次数.查询时只需找出在字典树上的 ...

  7. HihoCoder - 1445 后缀自动机 试水题

    题意:求子串个数 SAM中每个子串包含于某一个状态中 对于不同的状态\(u,v\),\(sub(u)∩sub(v)=NULL\) 因此答案就是对于所有的状态\(st\),\(ans=\sum_{st} ...

  8. 解题:APIO 2014 回文串

    题面 初见SAM 洛谷数据太弱了,我SAM写错了居然有90pts=.=??? SAM求一个子串$(l,r)$的出现次数:从右端点对应状态开始在parent树上倍增,当目标节点的$len$大于等于子串长 ...

  9. 【计蒜客】是男人就过 8 题--Pony.AI 题 A. A String Game 后缀自动机+SG函数

    [题目]A. A String Game [题意]给定目标串S和n个子串Ti,Alice和Bob轮流选择一个子串操作,必须且只能在子串末尾添加一个字符使得新串也是S的子串,不能操作即输,求胜利者.|S ...

随机推荐

  1. jdk带的一些工具,强悍

    这些工具有的已经接触到了,功能很强悍,但是使用也有点复杂(参数) 在代码中使用System.setProperty()或者在启动程序时使用-D选项设置代理服务器地址和端口 看看别人的研究: JDK自带 ...

  2. (2)分布式下的爬虫Scrapy应该如何做-关于对Scrapy的反思和核心对象的介绍

    本篇主要介绍对于一个爬虫框架的思考和,核心部件的介绍,以及常规的思考方法: 一,猜想 我们说的爬虫,一般至少要包含几个基本要素: 1.请求发送对象(sender,对于request的封装,防止被封) ...

  3. Mac下用tomcat搭建下载服务器

    1.下载tomcat 去官方网址: http://tomcat.apache.org/ 下载最新版 2.下载解压后,自己可以随便放在哪个文件夹下,自己记得路径即可.比如Users/你的用户名/Docu ...

  4. QSS 的选择器

    本文连接地址:http://www.qtdebug.com/QSS-Selector.html 选择器决定了 style sheet 作用于哪些 Widget,QSS 支持 CSS2 定义的所有选择器 ...

  5. 从传统IT快速走向公共云计算

    2年前有篇报道,说Facebook的每个运维同学至少能管理2万台服务器,这在当时的国内互联网引起了很大震动,按照传统IT的理解,每个运维同学能管理200台服务器已经很了不起了. 这些年来云计算发展非常 ...

  6. Linux 简单socket实现UDP通信

    服务器端 #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sy ...

  7. sql between and 边界问题

    1.不同的数据库对 BETWEEN...AND 操作符的处理方式是有差异的.需要自己测试 2.一般情况下.SQL Server中 between and是包括边界值的,not between不包括边界 ...

  8. not1,not2,bind1st,bind2nd

    例子需要包含头文件 #include <vector> #include <algorithm> #include <functional> bind1st和bin ...

  9. elasticsearch-1.7.1 (es Windows 64)

    elasticsearch-1.7.1 (es Windows 64) https://blog.csdn.net/qq_27093465/article/details/53544541 elast ...

  10. [洛谷P3690]【模板】Link Cut Tree (动态树)

    题目大意:给定$n$个点以及每个点的权值,要你处理接下来的$m$个操作.操作有$4$种.操作从$0到3编号.点从1到n编号. $0,x,y$:代表询问从$x$到$y$的路径上的点的权值的$xor$和. ...