题意:

给定一个长度不超过 10W 的只包含小写字母的字符串,从下标 0 到 n−1。从下标 0 开始操作,

每次对于下标 pos查找下标 pos 开始的子串中最长的在其他地方出现过的长度,
其他出现的位置要求起点在位置 pos 之前,然后 pos 移动到这个长度之后继续操作;
如果没有这样的最长串儿就直接 pos++,继续操作,直到 pos=n 结束。

对于上述两种操作,前者输出最大长度 K 以及这种串儿最左边出现的位置;
后者输出 −1 和 s[pos] 的 ASCII码值。

精炼一下题意:就是求出以下标 i 开头的后缀 与【0,i-1】开头的后缀的最长公共前缀

题解:

在线建立后缀自动机,然后将在线匹配即可

然后记录一下对应节点的right集合的最小值就是 某个后缀出现的最早位置

然后L[ i ] - maxlen 就是最早的位置

 #include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <ctime>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map> #define pi acos(-1.0)
#define eps 1e-9
#define fi first
#define se second
#define rtl rt<<1
#define rtr rt<<1|1
#define bug printf("******\n")
#define mem(a, b) memset(a,b,sizeof(a))
#define name2str(x) #x
#define fuck(x) cout<<#x" = "<<x<<endl
#define sfi(a) scanf("%d", &a)
#define sffi(a, b) scanf("%d %d", &a, &b)
#define sfffi(a, b, c) scanf("%d %d %d", &a, &b, &c)
#define sffffi(a, b, c, d) scanf("%d %d %d %d", &a, &b, &c, &d)
#define sfL(a) scanf("%lld", &a)
#define sffL(a, b) scanf("%lld %lld", &a, &b)
#define sfffL(a, b, c) scanf("%lld %lld %lld", &a, &b, &c)
#define sffffL(a, b, c, d) scanf("%lld %lld %lld %lld", &a, &b, &c, &d)
#define sfs(a) scanf("%s", a)
#define sffs(a, b) scanf("%s %s", a, b)
#define sfffs(a, b, c) scanf("%s %s %s", a, b, c)
#define sffffs(a, b, c, d) scanf("%s %s %s %s", a, b,c, d)
#define FIN freopen("../in.txt","r",stdin)
#define gcd(a, b) __gcd(a,b)
#define lowbit(x) x&-x
#define IO iOS::sync_with_stdio(false) using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const ULL seed = ;
const LL INFLL = 0x3f3f3f3f3f3f3f3fLL;
const int maxm = 8e6 + ;
const int INF = 0x3f3f3f3f;
const int mod = ;
const int maxn = 1e6 + ; struct Suffix_Automaton {
int last, tot, nxt[maxn << ][], fail[maxn << ];//last是未加入此字符前最长的前缀(整个串)所属的节点的编号
int len[maxn << ];// 最长子串的长度 (该节点子串数量 = len[x] - len[fa[x]])
int sz[maxn << ];// 被后缀链接的个数,方便求节点字符串的个数
LL num[maxn << ];// 该状态子串的数量
LL maxx[maxn << ];// 长度为x的子串出现次数最多的子串的数目
LL sum[maxn << ];// 该节点后面所形成的自字符串的总数
LL subnum, sublen;// subnum表示不同字符串数目,sublen表示不同字符串总长度
int X[maxn << ], Y[maxn << ]; // Y表示排名为x的节点,X表示该长度前面还有多少个
int minn[maxn << ], mx[maxn << ];//minn[i]表示多个串在后缀自动机i节点最长公共子串,mx[i]表示单个串的最长公共子串
int L[maxn << ]; void init() {
tot = last = ;
fail[] = len[] = ;
for (int i = ; i < ; i++) nxt[][i] = ;
} void extend(int c) {
int u = ++tot, v = last;
for (int i = ; i <= ; i++) nxt[u][i] = ;
fail[u] = ;
L[u] = len[u] = len[v] + ;
num[u] = ;
for (; v && !nxt[v][c]; v = fail[v]) nxt[v][c] = u;
if (!v) fail[u] = , sz[]++;
else if (len[nxt[v][c]] == len[v] + ) fail[u] = nxt[v][c], sz[nxt[v][c]]++;
else {
int now = ++tot, cur = nxt[v][c];
len[now] = len[v] + ;
L[now] = L[cur];
memcpy(nxt[now], nxt[cur], sizeof(nxt[cur]));
fail[now] = fail[cur];
fail[cur] = fail[u] = now;
for (; v && nxt[v][c] == cur; v = fail[v]) nxt[v][c] = now;
}
last = u;
//return len[last] - len[fail[last]];//多添加一个子串所产生不同子串的个数
} void get_num() {// 每个节点子串出现的次数
for (int i = ; i <= tot; i++) X[i] = ;
for (int i = ; i <= tot; i++) X[len[i]]++;
for (int i = ; i <= tot; i++) X[i] += X[i - ];
for (int i = ; i <= tot; i++) Y[X[len[i]]--] = i;
for (int i = tot; i >= ; i--) num[fail[Y[i]]] += num[Y[i]];
} void get_maxx(int n) {// 长度为x的子串出现次数最多的子串的数目
get_num();
for (int i = ; i <= tot; i++) maxx[len[i]] = max(maxx[len[i]], num[i]);
} void get_sum() {// 该节点后面所形成的自字符串的总数
get_num();
for (int i = tot; i >= ; i--) {
sum[Y[i]] = ;
for (int j = ; j <= ; j++)
sum[Y[i]] += sum[nxt[Y[i]][j]];
}
} void get_subnum() {//本质不同的子串的个数
subnum = ;
for (int i = ; i <= tot; i++) subnum += len[i] - len[fail[i]];
} void get_sublen() {//本质不同的子串的总长度
sublen = ;
for (int i = ; i <= tot; i++) sublen += 1LL * (len[i] + len[fail[i]] + ) * (len[i] - len[fail[i]]) / ;
} void get_sa() { // Y表示排名为x的节点,X表示该长度前面还有多少个
for (int i = ; i <= tot; i++) X[i] = ;
for (int i = ; i <= tot; i++) X[len[i]]++;
for (int i = ; i <= tot; i++) X[i] += X[i - ];
for (int i = ; i <= tot; i++) Y[X[len[i]]--] = i;
} void match(char s[]) {//多个串的最长公共子串
mem(mx, );
int n = strlen(s), p = , maxlen = ;
for (int i = ; i < n; i++) {
int c = s[i] - 'a';
if (nxt[p][c]) p = nxt[p][c], maxlen++;
else {
for (; p && !nxt[p][c]; p = fail[p]);
if (!p) p = , maxlen = ;
else maxlen = len[p] + , p = nxt[p][c];
}
mx[p] = max(mx[p], maxlen);
}
for (int i = tot; i; i--)
mx[fail[i]] = max(mx[fail[i]], min(len[fail[i]], mx[i]));
for (int i = tot; i; i--)
if (minn[i] == - || minn[i] > maxx[i]) minn[i] = mx[i];
} void get_kth(int k) {//求出字典序第K的子串
int pos = , cnt;
string s = "";
while (k) {
for (int i = ; i <= ; i++) {
if (nxt[pos][i] && k) {
cnt = nxt[pos][i];
if (sum[cnt] < k) k -= sum[cnt];
else {
k--;
pos = cnt;
s += (char) (i + 'a');
break;
}
}
}
}
cout << s << endl;
} } sam; int T, cas = ;
char s[maxn]; int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif
sfi(T);
while (T--) {
sfs(s);
int len = strlen(s);
sam.init();
printf("Case #%d:\n", cas++);
for (int i = ; i < len;) {
int p, maxlen;
for (p = , maxlen = ; i < len;) {
int c = s[i] - 'a';
if (!sam.nxt[p][c]) break;
else {
p = sam.nxt[p][c];
sam.extend((s[i] - 'a'));
i++, maxlen++;
}
}
if (maxlen) printf("%d %d\n", maxlen, sam.L[p] - maxlen);
else printf("-1 %d\n", s[i]), sam.extend((s[i] - 'a')), i++;
}
} #ifndef ONLINE_JUDGE
cout << "Totle Time : " << (double) clock() / CLOCKS_PER_SEC << "s" << endl;
#endif
return ;
}

Alice's Classified Message HDU - 5558 后缀自动机求某个后缀出现的最早位置的更多相关文章

  1. hdu5558 Alice's Classified Message

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=5558 题目: Alice's Classified Message Time Limit: 1 ...

  2. (HDU 5558) 2015ACM/ICPC亚洲区合肥站---Alice's Classified Message(后缀数组)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5558 Problem Description Alice wants to send a classi ...

  3. HUID 5558 Alice's Classified Message 后缀数组+单调栈+二分

    http://acm.hdu.edu.cn/showproblem.php?pid=5558 对于每个后缀suffix(i),想要在前面i - 1个suffix中找到一个pos,使得LCP最大.这样做 ...

  4. str2int HDU - 4436 后缀自动机求子串信息

    题意: 给出 n 个串,求出这 n 个串所有子串代表的数字的和. 题解; 首先可以把这些串构建后缀自动机(sam.last=1就好了), 因为后缀自动机上从 root走到的任意节点都是一个子串,所有可 ...

  5. 洛谷P4248 [AHOI2013]差异(后缀自动机求lcp之和)

    题目见此 题解:首先所有后缀都在最后一个np节点,然后他们都是从1号点出发沿一些字符边到达这个点的,所以下文称1号点为根节点,我们思考一下什么时候会产生lcp,显然是当他们从根节点开始一直跳相同节点的 ...

  6. BZOJ 3998: [TJOI2015]弦论 后缀自动机 后缀自动机求第k小子串

    http://www.lydsy.com/JudgeOnline/problem.php?id=3998 后缀自动机应用的一个模板?需要对len进行一个排序之后再统计每个出现的数量,维护的是以该字符串 ...

  7. 【后缀自动机】hihocoder1449 后缀自动机三·重复旋律6

    解题方法提示 小Hi:上次我们已经学习了后缀自动机了,今天我们再来解决一个用到后缀自动机的问题. 小Ho:好!那我们开始吧! 小Hi:现在我们要对K=1..length(S)求出所有长度为K的子串中出 ...

  8. 【后缀自动机】hihocoder1445 后缀自动机二·重复旋律5

    解题方法提示 小Hi:本周的题目其实就是给定一个字符串S,要求出S的所有不同子串的数目.小Ho你知道如何快速求解么? 小Ho:我们最近在讨论后缀自动机,所以肯定是和后缀自动机有关!根据上周学习的SAM ...

  9. 【后缀自动机】hihocoder1441 后缀自动机一·基本概念

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi:今天我们来学习一个强大的字符串处理工具:后缀自动机(Suffix Automaton,简称SAM).对于一个字符串 ...

随机推荐

  1. python调用tushare港股通每月成交统计

    接口:ggt_monthly 描述:港股通每月成交信息,数据从2014年开始 限量:单次最大1000 积分:用户积5000积分可调取,请自行提高积分,具体请参阅本文最下方积分获取办法 注:tushar ...

  2. 菩提圣心诀---zabbix自定义key监控oracle连接状态(python脚本)

    目的:此次实验目的是为了zabbix服务端能够实时监控某服务器上oracle实例能否正常连接 环境:1.zabbix_server 2.zabbix_agent(含有oracle) 主要知识点: 1. ...

  3. 12-vim-撤销和删除命令-02-删除文本

    删除文本 命令 英文 功能 x cut 删除光标所在字符 d(移动命令) delete 删除移动命令对应的内容 dd delete 删除光标所在行 D delete 从光标位置删除至行尾 注: 如果使 ...

  4. MQ入门介绍

    MQ全称为Message Queue, 消息队列(MQ)是一种应用程序对应用程序的通信方法.应用程序通过写和检索出入列队的针对应用程序的数据(消息)来通信,而无需专用连接来链接它们.消息传递指的是程序 ...

  5. CG-CTF CRYPTO部分wp

    1,easybase64解密得flag 2,keyboard键盘码,在键盘上画画得flag:areuhack 3,异性相吸根据提示,写脚本 with open('密文.txt')as a: a=a.r ...

  6. Socket网络编程--初级

    如果想开发一个基于TCP/IP协议的网络程序,应用程序之间则主要通过Socket交换数据 .NET Socket支持四种编程模式 1.居于阻塞模式的Socket编程 2.”非阻塞“模式的Socket编 ...

  7. teb教程1

    http://wiki.ros.org/teb_local_planner/Tutorials/Setup%20and%20test%20Optimization 简介:本部分关于teb怎样优化轨迹以 ...

  8. 热修复框架Tinker的从0到集成之路(转)

    转自:http://blog.csdn.net/lisdye2/article/details/54411727 热修复框架Tinker的从0到集成之路 转载请标明出处: http://blog.cs ...

  9. 9、Python 连接 PostgreSQL数据库 -- psycopg2

    1.cmd  pip install psycopg2 -- 提示错误信息 2.pip show pip   -->查看当前pip版本 3.python -m pip install --upg ...

  10. 【JavaWeb项目】一个众筹网站的开发(五)后台用户登录功能

    用户模块 1)注册 表单校验,使用校验插件 用户密码需要加密存储 注册成功后来到管理控制台,将用户放在session中,防止以后获取 以后用户经常获取用户id,使用mabatis主键自增策略,保存用户 ...