【hdu4436/LA6387-str2int】sam处理不同子串
题意:给出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处理不同子串的更多相关文章
- 后缀自动机(SAM)
*在学习后缀自动机之前需要熟练掌握WA自动机.RE自动机与TLE自动机* 什么是后缀自动机 后缀自动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂度构造,能够接受一个字符 ...
- 后缀自己主动机(SAM)学习指南
*在学习后缀自己主动机之前须要熟练掌握WA自己主动机.RE自己主动机与TLE自己主动机* 什么是后缀自己主动机 后缀自己主动机 Suffix Automaton (SAM) 是一个用 O(n) 的复杂 ...
- 【算法】后缀自动机(SAM) 例题
算法介绍见:http://www.cnblogs.com/Sakits/p/8232402.html 广义SAM资料:https://www.cnblogs.com/phile/p/4511571.h ...
- hihoCoder 后缀自动机三·重复旋律6
后缀自动机三·重复旋律6 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi ...
- BZOJ 3926: [Zjoi2015]诸神眷顾的幻想乡
3926: [Zjoi2015]诸神眷顾的幻想乡 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1017 Solved: 599[Submit][S ...
- 51nod1647 小Z的trie
题意:给你n个字符串,m次查询,每次问你第p个字符串的s到t的字符串在n个字符串建成的字典树上出现了多少次 题解:先建出字典树,在字典树上拓展sam,记录每个子串的出现次数.查询时只需找出在字典树上的 ...
- HihoCoder - 1445 后缀自动机 试水题
题意:求子串个数 SAM中每个子串包含于某一个状态中 对于不同的状态\(u,v\),\(sub(u)∩sub(v)=NULL\) 因此答案就是对于所有的状态\(st\),\(ans=\sum_{st} ...
- 解题:APIO 2014 回文串
题面 初见SAM 洛谷数据太弱了,我SAM写错了居然有90pts=.=??? SAM求一个子串$(l,r)$的出现次数:从右端点对应状态开始在parent树上倍增,当目标节点的$len$大于等于子串长 ...
- 【计蒜客】是男人就过 8 题--Pony.AI 题 A. A String Game 后缀自动机+SG函数
[题目]A. A String Game [题意]给定目标串S和n个子串Ti,Alice和Bob轮流选择一个子串操作,必须且只能在子串末尾添加一个字符使得新串也是S的子串,不能操作即输,求胜利者.|S ...
随机推荐
- hive报错:Caused by: ERROR XBM0H: Directory /var/lib/hive/metastore/metastore_db cannot be created.
在cdh集群中,删除之前的hive服务,然后将hive添加到其他节点,然后再通过hive客户端连接hive报错: Caused by: ERROR XJ041: Failed to create da ...
- Returning Values from Bash Functions
转自:https://www.linuxjournal.com/content/return-values-bash-functions Bash functions, unlike function ...
- Android TextView 单行文本的坑
这是android系统的一个bug,描述如下:https://code.google.com/p/android/issues/detail?id=33868 具体来说就是当一个TextView设置了 ...
- Ubuntu下使用Git_6
这回真的是最后一篇了,哈哈,改写提交. 这里这部分在目前的学习阶段还没有用到,所以,这里将不在有实验的部分,在下面的链接中有详细的介绍 这也是我第一讲一个网站的内容完成的学习完成,这这部分,我讲简单的 ...
- 第四篇 Python循环
While 循环 For 循环
- 孤荷凌寒自学python第七十三天开始写Python的第一个爬虫3
孤荷凌寒自学python第七十三天开始写Python的第一个爬虫3 (完整学习过程屏幕记录视频地址在文末) 今天在上一天的基础上继续完成对我的第一个代码程序的书写. 直接上代码.详细过程见文末屏幕录像 ...
- npm 版本问题
STF之问题篇 https://yq.aliyun.com/articles/221602 装完成后输入stf doctor查看工具依赖是否正确,安装教程可以参考我之前写的,这里不再多说,直接说问题. ...
- windows基础知识(win7)
右击 显示: 对设备进行管理: 在计算机属性中,开远程连接 控制面板: 控制面板下的操作中心: 控制面板下的管理工具: 控制面板下的默认程序: 控制面板下的日期时间: 控制面板下的鼠标: 控制面板下的 ...
- BZOJ 4276 [ONTAK2015]Bajtman i Okrągły Robin 费用流+线段树优化建图
Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2],...,[b[i]-1,b[i]]这么多段长度为1时间中选出一个时间进行抢劫,并计划抢 ...
- iOS-UIImageView播放动画
NSArray *gifArray = [NSArray arrayWithObjects:[UIImage imageNamed:@"lanya1"],[UIImage imag ...