问题:

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. Zipper (DP)

    Zipper Given three strings, you are to determine whether the third string can be formed by combining ...

  2. An Ordinary Game(简单推导)

    An Ordinary Game Time limit : 2sec / Memory limit : 256MB Score : 500 points Problem Statement There ...

  3. Frobenius inner product

    https://en.wikipedia.org/wiki/Frobenius_inner_product Frobenius norm

  4. 【python】-- json & pickle、xml、requests、hashlib、shelve、shutil、configparser、subprocess

    json & pickle Python中用于序列化的两个模块 json     用于[字符串]和 [python基本数据类型] 间进行转换 pickle   用于[python特有的类型] ...

  5. struts2 封装获取表单数据的方式

    一.属性封装 1.在action中设置成员变量,变量名与表单中的name属性值相同 2.生成变量的set方法 实例 获取用户输入的用户名和密码 jsp页面 java代码 二.模型驱动(常用) 1.ac ...

  6. ABAP动态生成经典应用之Dynamic SQL Excute 程序

    [转自http://blog.csdn.net/mysingle/article/details/678598]开发说明:在SAP的系统维护过程中,有时我们需要修改一些Table中的数据,可是很多Ta ...

  7. abap Excel 导入

    ABAP 将EXECL数据导入SAP内表的几个步骤. 本文转自:http://blog.csdn.net/szlaptop/article/details/8663451   http://www.c ...

  8. mysql存储引擎(待补充)

    数据库中的表也应该有不同的类型,表的类型不同,会对应mysql不同的存取机制,表类型又称为存储引擎 存储引擎说白了就是如何存取数据.如何为存储的数据建立索引和如何更新.查询数据等技术的实现方法.因为在 ...

  9. 基于事件驱动的前端通信框架(封装socket.io)

    socket.io的使用可以很轻松的实现websockets,兼容所有浏览器,提供实时的用户体验,并且为程序员提供客户端与服务端一致的编程体验.但是在使用socket.io的过程中,由于业务需求需要同 ...

  10. PAT 天梯赛 L2-016. 愿天下有情人都是失散多年的兄妹 【BFS】

    题目链接 https://www.patest.cn/contests/gplt/L2-016 思路 用BFS 每层 遍历当代 并且查找当代是否有重复 有重复就跳出 然后 POP 并且将他们的下一代 ...