问题:

Amateur astronomers Tom and Bob try to find radio broadcasts of extraterrestrial civilizations in the air. Recently they received some strange signal and represented it as a word consisting of small letters of the English alphabet. Now they wish to decode the signal. But they do not know what to start with.
      They think that the extraterrestrial message consists of words, but they cannot identify them. Tom and Bob call a subword of the message a potential word if it has at least two non-overlapping occurrences in the message.

For example, if the message is “abacabacaba”, “abac” is a potential word, but “acaba” is not because two of its occurrences overlap.
      Given a message m help Tom and Bob to find the number of potential words in it.

Input

      Input file contains one string that consists of small letters of the English alphabet. The length of the message doesn’t exceed 10 000.

Output

      Output one integer number — the number of potential words in a message.

Sample Input

abacabacaba

Sample Output

15

题意:

求字符串里的不相交重复字串的个数和。

思路;

后缀自动机:记录每个状态的最先出现和最后一次出现的位置,就可以判断是否出现了多次,以及是否相交。(116ms)

后缀数组:。。。

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<memory>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=;
char chr[maxn];
int Head[maxn],Lates[maxn],Now;
struct SAM
{
int sz,Last,ch[maxn][],slink[maxn],maxlen[maxn],ans;
int c[maxn],pos[maxn],num[maxn];
void init()
{
Last=sz=;Head[]=Lates[]=;ans=;
memset(ch[],,sizeof(ch[]));
memset(Lates,,sizeof(Lates));
memset(Head,,sizeof(Head));
}
void add(int x)
{
int np=++sz,p=Last;Last=np;num[np]=;
Head[np]=Now;Lates[np]=Now; memset(ch[np],,sizeof(ch[np]));
maxlen[np]=maxlen[p]+;
while(p&&!ch[p][x]) ch[p][x]=np,p=slink[p];
if(!p) slink[np]=;
else {
int q=ch[p][x];
if(maxlen[q]==maxlen[p]+) slink[np]=q;
else {
int nq=++sz; num[nq]=;
memcpy(ch[nq],ch[q],sizeof(ch[q])); Head[nq]=Head[q];Lates[nq]=Lates[q];
slink[nq]=slink[q],slink[np]=slink[q]=nq;
maxlen[nq]=maxlen[p]+;
while(p&&ch[p][x]==q) ch[p][x]=nq,p=slink[p];
}
}
while(np>) Lates[np]=Now,np=slink[np];
}
void solve()
{
for(int i=;i<=sz;i++) {
int dis=Lates[i]-Head[i];
int mi=min(dis,maxlen[i]);
if(mi>=maxlen[slink[i]]) ans+=mi-maxlen[slink[i]];
}
printf("%d\n",ans);
}
};
SAM sam;
int main()
{
sam.init(); int l;
scanf("%s",chr); l=strlen(chr);
for(Now=;Now<l;Now++) sam.add(chr[Now]-'a'); sam.solve();
return ;
}

也可以刷新完了再跟新最后一次出现的位置(拓扑排序)(4ms)(优化一下居然时间排名第一了。。。)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<memory>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=;
char chr[maxn];
int Head[maxn],Lates[maxn],Now;
struct SAM
{
int sz,Last,ch[maxn][],slink[maxn],maxlen[maxn],ans;
int c[maxn],pos[maxn],num[maxn];
void init()
{
Last=sz=;Head[]=Lates[]=;ans=;
memset(ch[],,sizeof(ch[]));
memset(Lates,,sizeof(Lates));
memset(Head,,sizeof(Head));
}
void add(int x)
{
int np=++sz,p=Last;Last=np;num[np]=;
Head[np]=Now;Lates[np]=Now; memset(ch[np],,sizeof(ch[np]));
maxlen[np]=maxlen[p]+;
while(p&&!ch[p][x]) ch[p][x]=np,p=slink[p];
if(!p) slink[np]=;
else {
int q=ch[p][x];
if(maxlen[q]==maxlen[p]+) slink[np]=q;
else {
int nq=++sz; num[nq]=;
memcpy(ch[nq],ch[q],sizeof(ch[q])); Head[nq]=Head[q];Lates[nq]=Lates[q];
slink[nq]=slink[q],slink[np]=slink[q]=nq;
maxlen[nq]=maxlen[p]+;
while(p&&ch[p][x]==q) ch[p][x]=nq,p=slink[p];
}
}
//while(np>1) Lates[np]=Now,np=slink[np];
}
void sort()
{
for(int i=;i<=sz;i++) c[i]=;
for(int i=;i<=sz;i++) c[maxlen[i]]++;
for(int i=;i<=sz;i++) c[i]+=c[i-];
for(int i=;i<=sz;i++) pos[c[maxlen[i]]--]=i;
for(int i=sz;i>=;i--) Lates[slink[pos[i]]]=max(Lates[pos[i]],Lates[slink[pos[i]]]);
}
void solve()
{ ans=;
for(int i=;i<=sz;i++) {
int dis=Lates[i]-Head[i];
int mi=min(dis,maxlen[i]);
if(mi>=maxlen[slink[i]]) ans+=mi-maxlen[slink[i]];
}
printf("%d\n",ans);
}
};
SAM sam;
int main()
{
sam.init();int l;
scanf("%s",chr);l=strlen(chr);
for(Now=;Now<l;Now++) sam.add(chr[Now]-'a');
sam.sort();sam.solve();
return ;
}

ACdream1430SETI(后缀自动机)的更多相关文章

  1. BZOJ 后缀自动机四·重复旋律7

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

  2. 【Codeforces235C】Cyclical Quest 后缀自动机

    C. Cyclical Quest time limit per test:3 seconds memory limit per test:512 megabytes input:standard i ...

  3. 【hihocoder#1413】Rikka with String 后缀自动机 + 差分

    搞了一上午+接近一下午这个题,然后被屠了个稀烂,默默仰慕一晚上学会SAM的以及半天4道SAM的hxy大爷. 题目链接:http://hihocoder.com/problemset/problem/1 ...

  4. 【BZOJ-3998】弦论 后缀自动机

    3998: [TJOI2015]弦论 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 2018  Solved: 662[Submit][Status] ...

  5. HDU 4622 Reincarnation (查询一段字符串的不同子串个数,后缀自动机)

    Reincarnation Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/65536 K (Java/Others)To ...

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

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

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

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

  8. 数据结构:后缀自动机 WJMZBMR讲稿的整理和注释

    链接放在这里,有点难理解,至少我个人是的. 后缀自动机是一种有限状态自动机,其功能是识别字符串是否是母串的后缀.它能解决的问题当然不仅仅是判断是不是后缀这种事,跟字符串的连续子串有关的问题都可以往这个 ...

  9. 【SPOJ】7258. Lexicographical Substring Search(后缀自动机)

    http://www.spoj.com/problems/SUBLEX/ 后缀自动机系列完成QAQ...撒花..明天or今晚写个小结? 首先得知道:后缀自动机中,root出发到任意一个状态的路径对应一 ...

随机推荐

  1. python 基础 9.7 创建表

    一. 创建表 #/usr/bin/python #-*- coding:utf-8 -*- #@Time   :2017/11/22 18:05 #@Auther :liuzhenchuan #@Fi ...

  2. 你可能不知道的5个功能强大的 HTML5 API

    HTML5 新增了许多重要的特性,像 video.audio 和 canvas 等等,这些特性使得能够很容易的网页中包含多媒体内容,而不需要任何的插件或者 API.而其它的新元素,例如 section ...

  3. TP框架的增删改

    TP添加数据有三种方式 1. //1.使用数组添加 $n = M("nation"); $arr = array("Code"=>"n007&q ...

  4. Sum of Remainders(数学题)

    F - Sum of Remainders Time Limit:2000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I ...

  5. 还在用 kill -9 停机?这才是最优雅的姿势(转)

    _ 最近瞥了一眼项目的重启脚本,发现运维一直在使用 kill-9<pid> 的方式重启 springboot embedded tomcat,其实大家几乎一致认为:kill-9<pi ...

  6. MySQL5.7.26 忘记Root密码小计

    以前直接修改mysql.user就ok了,现在不行了,正好虚拟机MySQL的root密码忘记了,就简单记录下:(本方法不适合互联网线上项目,除非你不在意这段时间的损失) PS:以UbuntuServe ...

  7. 阿里云centos7搭建php+nginx环境

    阿里云Centos搭建lnmp(php7.1+nginx+mysql5.7) https://jingyan.baidu.com/article/215817f7a10bfb1eda14238b.ht ...

  8. Android Dev Tips

    Ref:Android Service与Activity之间通信的几种方式 Ref:基础总结篇之五:BroadcastReceiver应用详解 Ref:Android Activity和Intent机 ...

  9. Crontab使用详解

    第1列分钟1-59第2列小时1-23(0表示子夜)第3列日1-31第4列月1-12第5列星期0-6(0表示星期天)第6列要运行的命令 下面是crontab的格式:分 时 日 月 星期 要运行的命令 这 ...

  10. Docker的前世今生

    核心知识点: 1.Docker的构想:对应用的封装.分发.部署.运行的生命周期的管理,一次封装到处运行 2.Docker的优点:一站式解决方案 3.Docker由LXC演变而来,迟迟没有集成到Linu ...