Reincarnation HDU - 4622 (后缀自动机)
Reincarnation
\]
题意
给出一个字符串 \(S\),然后给出 \(m\) 次查询,每次给出一个 \([l, r]\) 区间,每次求出这个区间内有多少个不同的子串。
思路
首先知道给出一个字符串,如何求出其不同子串的个数,有三种方法。
- 利用后缀数组,\(\sum_{i=2}^{n} len-sa[i]+1-height[i]\) 就是答案
- 利用后缀自动机,\(dp[i]\) 表示第 \(i\) 个节点拥有的字符串个数,可以让 \(v \in u'next\),\(dp[u] += dp[v]\),最后的 \(dp[1]-1\) 就是答案。
- 利用后缀自动机,\(\sum_{i=2}^{sz} node[i].len - node[father].len\) 就是答案。
这里用到了第三种方法,因为字符串的长度很小,所以直接 \(O(N^{2})\) 暴力预处理出两两之间的字符串长度并保存起来,最后 \(O(1)\) 查询。
#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#define lowbit(x) x & (-x)
#define mes(a, b) memset(a, b, sizeof a)
#define fi first
#define se second
#define pii pair<int, int>
#define INOPEN freopen("in.txt", "r", stdin)
#define OUTOPEN freopen("out.txt", "w", stdout)
typedef unsigned long long int ull;
typedef long long int ll;
const int maxn = 2e3 + 10;
const int maxm = 1e5 + 10;
const ll mod = 1e9 + 7;
const ll INF = 1e18 + 100;
const int inf = 0x3f3f3f3f;
const double pi = acos(-1.0);
const double eps = 1e-8;
using namespace std;
int n, m;
int cas, tol, T;
struct SAM {
struct Node {
int next[27];
int fa, len;
void init() {
mes(next, 0);
len = fa = 0;
}
} node[maxn<<1];
int last, sz;
void init() {
last = sz = 1;
node[sz].init();
}
void insert(int k) {
int p = last, np = last = ++sz;
node[np].init();
node[np].len = node[p].len + 1;
for(; p&&!node[p].next[k]; p=node[p].fa)
node[p].next[k] = np;
if(p == 0) {
node[np].fa = 1;
} else {
int q = node[p].next[k];
if(node[q].len == node[p].len+1) {
node[np].fa = q;
} else {
int nq = ++sz;
node[nq] = node[q];
node[nq].len = node[p].len+1;
node[np].fa = node[q].fa = nq;
for(; p&&node[p].next[k]==q; p=node[p].fa)
node[p].next[k] = nq;
}
}
}
int calc() {
return node[last].len - node[node[last].fa].len;
}
} sam;
char s[maxn];
int dp[maxn][maxn];
int main() {
scanf("%d", &T);
while(T--) {
scanf("%s", s+1);
int len = strlen(s+1);
mes(dp, 0);
for(int i=1; i<=len; i++) {
sam.init();
for(int j=i; j<=len; j++) {
sam.insert(s[j]-'a'+1);
dp[i][j] = dp[i][j-1] + sam.calc();
}
}
scanf("%d", &n);
for(int i=1, l, r; i<=n; i++) {
scanf("%d%d", &l, &r);
printf("%d\n", dp[l][r]);
}
}
return 0;
}
Reincarnation HDU - 4622 (后缀自动机)的更多相关文章
- HDU 4622 (后缀自动机)
HDU 4622 Reincarnation Problem : 给一个串S(n <= 2000), 有Q个询问(q <= 10000),每次询问一个区间内本质不同的串的个数. Solut ...
- HDU 5442 后缀自动机(从环字符串选定一个位置 , 时针或顺时针走一遍,希望得到字典序最大)
http://acm.hdu.edu.cn/showproblem.php?pid=5442 题目大意: 给定一个字符串,可理解成环,然后选定一位置,逆时针或顺时针走一遍,希望得到字典序最大,如果同样 ...
- HDU 4436 (后缀自动机)
HDU 4436 str2int Problem : 给若干个数字串,询问这些串的所有本质不同的子串转换成数字之后的和. Solution : 首先将所有串丢进一个后缀自动机.由于这道题询问的是不同的 ...
- HDU 4416 (后缀自动机)
HDU 4416 Good Article Good sentence Problem : 给一个串S,和一些串T,询问S中有多少个子串没有在T中出现. Solution :首先对所有的T串建立后缀自 ...
- HDU 5442 后缀自动机+kmp
题目大意: 给定一个字符串,可理解成环,然后选定一位置,逆时针或顺时针走一遍,希望得到字典序最大,如果同样大,希望找到起始位置最小的,如果还相同,就默认顺时针 比赛一直因为处理最小位置出错,一结束就想 ...
- hdu 6208(后缀自动机、或者AC自动机
题意:给你n个字符串,问你是否存在一个字符串可以从中找到其他n-1个字符串. 思路:其实很简单,找到最长的那个字符串对他进行匹配,看是否能匹配到n-1个字符串. 可以用AC自动机或者后缀自动机做,但是 ...
- Boring counting HDU - 3518 后缀自动机
题意: 对于给出的字符串S, 长度不超过1000, 求其中本质不同的子串的数量, 这些子串满足在字符串S中出现了至少不重合的2次 题解: 将串放入后缀自动机中然后求出每一个节点对应的子串为后缀的子串出 ...
- Alice's Classified Message HDU - 5558 后缀自动机求某个后缀出现的最早位置
题意: 给定一个长度不超过 10W 的只包含小写字母的字符串,从下标 0 到 n−1.从下标 0 开始操作, 每次对于下标 pos查找下标 pos 开始的子串中最长的在其他地方出现过的长度,其他出现的 ...
- str2int HDU - 4436 后缀自动机求子串信息
题意: 给出 n 个串,求出这 n 个串所有子串代表的数字的和. 题解; 首先可以把这些串构建后缀自动机(sam.last=1就好了), 因为后缀自动机上从 root走到的任意节点都是一个子串,所有可 ...
随机推荐
- Docker在Windows上的初体验
作为Docker的初学者,我有几个疑问,找到了答案,并实践了一下,希望对和我一样的初学者有帮助: 1.Docker是什么? 大家对虚拟机应该比较熟悉,虚拟机和docker都是为了实现隔离. 虚拟机隔离 ...
- C++指针与数组、函数、动态内存分配
C++指针 指针是用来存储地址的变量. 对于二维数组来说: a:代表的是首行地址: *a:代表的是首元素地址: **a:首元素: a+1:第二行地址: *a+2:首先*a是首元素地址,在首元素地址上+ ...
- CRLF will be replaced by LF in XXX when git commit
转载自Git-warning: CRLF will be replaced by LF in XXX 今天,普通平凡的一天,平凡的使用 git add .,然后又出现一个之前没遇到的错误提示 . 真开 ...
- Java异常的10个关键知识点
前言 总结了Java异常十个关键知识点,面试或者工作中都有用哦,加油. 一. 异常是什么 异常是指阻止当前方法或作用域继续执行的问题.比如你读取的文件不存在,数组越界,进行除法时,除数为0等都会导致异 ...
- (7)ASP.NET Core 中的错误处理
1.前言 ASP.NET Core处理错误环境区分为两种:开发环境和非开发环境.●开发环境:开发人员异常页.●非开发环境:异常处理程序页.状态代码页.在Startup.Configure方法里面我们会 ...
- tomcat端口修改后在Eclipse中启动无效问题解决
原文:https://blog.csdn.net/yangyiqian/article/details/40262039 问题:在conf目录修改了server.xml配置中的节点 <Conn ...
- Vertx与Spring配合完成DML操作
服务启动: public static void main( String[] args ) { ApplicationContext context = new AnnotationConfigAp ...
- 03、新手必须掌握的Linux命令
Ⅰ. 常用系统工作命令 1. echo 命令 echo命令用于在终端输出字符串货变量提取后的值,格式为"echo [字符串 | $变量]" 例:把指定字符串"LinxuH ...
- Beego 学习笔记15:布局页面
页面布局 1> 一个html页面由:head部分,body部分,内部css,内部js,外联css,外联的js这几部分组成.因此,一个布局文件也就需要针对这些进行拆分. 2> ...
- JavaScript 之 Date对象
Date对象 Date 是一个构造函数,首先要通过 new Date() 来创建实例对象,提供实例成员. 创建 Date 实例用来处理日期和时间.Date 对象基于 1970年1月1日(世界标准时间 ...