题意:给出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. ABP框架插件开发

    http://personball.com/abp/2017/08/21/abp-how-to-use-plugin

  2. 30分钟快速搭建Web CRUD的管理平台--django神奇魔法

    加上你的准备的时间,估计30分钟完全够用了,因为最近在做爬虫管理平台,想着快速开发,没想到python web平台下有这么非常方便的框架,简洁而优雅.将自己的一些坑总结出来,方便给大家的使用. 准备环 ...

  3. 【个人训练】(UVa146)ID Codes

    题意与解析 这题其实特别简单,求给定排列的后继.使用stl(next_permutation)可以方便地解决这个问题.但是,想要自己动手解就是另外一回事了.我的解法是从后往前找到第一个$a_i$比$a ...

  4. WebSocket 与 HTTP/2

    个人笔记 WebSocket WebSocket 是一个双向通信协议,它在握手阶段采用 HTTP/1.1 协议(暂时不支持 HTTP/2). 握手过程如下: 首先客户端向服务端发起一个特殊的 HTTP ...

  5. C#的Response.BinaryWrite图片乱码问题

    今天学习Response对象,该对象的有很多的输出方式,其中有一个binaryWrite可以输出图片,但是在输出图片一开始出现了乱码,后来通过百度得到解决: 代码: FileStream stream ...

  6. lintcode-100-删除排序数组中的重复数字

    100-删除排序数组中的重复数字 素只出现一次,并且返回新的数组的长度. 不要使用额外的数组空间,必须在原地没有额外空间的条件下完成. 样例 给出数组A =[1,1,2],你的函数应该返回长度2,此时 ...

  7. java05笔记

  8. JSON教程(1)

    JSON:JavaScript对象表示发即JavaScript Object Notation. JSON是存储和交换文本信息的语法.类似XML. JSON比XML更小,更快,更易解析. { &quo ...

  9. C#重载和重写

    Overload:重载就是在同一个类中,方法名相同,参数列表不同.参数列表不同包括:参数的个数不同,参数类型不同. using System; using System.Collections.Gen ...

  10. JSP语法,运行机理等

    JSP是几年前就接触了,但是用归用,很多实际的意义含义等还是不太明白,借此机会,梳理一下. 1.JSP运行原理:当浏览器web应用服务器请求一个JSP页面时,Web应用服务器将其转换成一个Servle ...