HDU 6194 string string string ——(2017沈阳网络赛,后缀数组)
思路见:http://blog.csdn.net/aozil_yang/article/details/77929216。
代码如下:
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int N = 1e5 + ;
typedef long long ll; /**
* sa[i]:表示排在第i位的后缀的起始下标
* rank[i]:表示后缀suffix(i)排在第几
* height[i]:sa[i-1] 与 sa[i]的LCP(最长公共前缀)值
*
* */
/*
如果整数的话模板改成int.
加一个数a[n] = 0 。 这样他的排名是第一个。
construct(a,n+1); 字符串的话。
len = strlen(str);
construct(s,strlen(s)+1);
排名第0的是个空字符串。 height[i]:sa[i-1] 与 sa[i]的LCP(最长公共前缀)值
所以height[1] = 0;
rank[len] = 0;
sa[0] = len;
*/
int sa[N],rnk[N],height[N];
void construct(const char *s,int n,int m = ) {
static int t1[N],t2[N],c[N];
int *x = t1,*y = t2;
int i,j,k,p,l;
for (i = ; i < m; ++ i) c[i] = ;
for (i = ; i < n; ++ i) c[x[i] = s[i]] ++;
for (i = ; i < m; ++ i) c[i] += c[i - ];
for (i = n - ; i >= ; -- i) sa[--c[x[i]]] = i;
for (k = ; k <= n; k <<= ) {
p = ;
for (i = n - k; i < n; ++ i) y[p++] = i;
for (i = ; i < n; ++ i) if (sa[i] >= k) y[p++] = sa[i] - k;
for (i = ; i < m; ++ i) c[i] = ;
for (i = ; i < n; ++ i) c[x[y[i]]] ++;
for (i = ; i < m; ++ i) c[i] += c[i - ];
for (i = n - ; i >= ; -- i) sa[--c[x[y[i]]]] = y[i];
std::swap(x,y);
p = ; x[sa[]] = ;
for (i = ; i < n; ++ i)
x[sa[i]] = y[sa[i - ]] == y[sa[i]]
&& y[sa[i - ] + k] == y[sa[i] + k] ? p - : p ++;
if (p >= n) break;
m = p;
}
for (i = ; i < n; ++ i) rnk[sa[i]] = i;
for (i = ,l = ; i < n; ++ i) {
if (rnk[i]) {
j = sa[rnk[i] - ];
while (s[i + l] == s[j + l]) l++;
height[rnk[i]] = l;
if (l) l--;
}
}
} int st_min[N][];
int preLog[N];
int n;
void init_rmq()
{
preLog[] = ;
for(int i=;i<=n;i++)
{
preLog[i] = preLog[i-];
if(( << preLog[i] + ) == i) preLog[i]++;
}
for(int i=n;i>=;i--)
{
st_min[i][] = height[i];
for(int j=;(i+(<<j)-)<=n;j++)
{
st_min[i][j] = min(st_min[i][j-], st_min[i+(<<j-)][j-]);
}
}
}
int query_min(int l,int r)
{
int len = r - l + , k = preLog[len];
return min(st_min[l][k], st_min[r-(<<k)+][k]);
}
char s[N];
int lcp(int l, int r)
{
/*int ql = rnk[l], qr = rnk[r];
if(ql > qr) swap(ql, qr);
if(ql == qr) return n - l;
return query_min(ql+1, qr);*/
// l and r are number in rnk.
if(l == r) return n - sa[l];
return query_min(l+, r);
} int main()
{
int T; scanf("%d",&T);
while(T--)
{
int k; scanf("%d",&k);
scanf("%s",s);
n = strlen(s);
s[n] = ;
construct(s, n+);
init_rmq(); ll ans = ;
for(int i=;i+k-<=n;i++)
{
ans += lcp(i, i+k-);
if(i- >= ) ans -= lcp(i-, i+k-);
if(i+k <= n) ans -= lcp(i, i+k);
if(i- >= && i+k <= n) ans += lcp(i-, i+k);
}
printf("%I64d\n",ans);
}
return ;
}
最后仍然需要注意的是我sa的模板中,除了rnk数组其他都是0-base的。
HDU 6194 string string string ——(2017沈阳网络赛,后缀数组)的更多相关文章
- HDU 6194 string string string 2017沈阳网络赛 后缀数组
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6194 题意:告诉你一个字符串和k , 求这个字符串中有多少不同的子串恰好出现了k 次. 解法:后缀数组 ...
- 【转】HDU 6194 string string string (2017沈阳网赛-后缀数组)
转自:http://blog.csdn.net/aozil_yang/article/details/77929216 题意: 告诉你一个字符串和k , 求这个字符串中有多少不同的子串恰好出现了k 次 ...
- HDU 6197 array array array 2017沈阳网络赛 LIS
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6197 题意:给你n个数,问让你从中删掉k个数后(k<=n),是否能使剩下的序列为非递减或者非递增 ...
- HDU 6200 2017沈阳网络赛 树上区间更新,求和
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6200 题意:给个图,有2种操作,一种是加一条无向边,二是查询u,v之间必须有的边的条数,所谓必须有的边 ...
- HDU 6199 2017沈阳网络赛 DP
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6199 题意:n堆石子,Alice和Bob来做游戏,一个人选择取K堆那么另外一个人就必须取k堆或者k+1 ...
- HDU 6203 2017沈阳网络赛 LCA,DFS+树状数组
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6203 题意:n+1 个点 n 条边的树(点标号 0 ~ n),有若干个点无法通行,导致 p 组 U V ...
- HDU 6205 2017沈阳网络赛 思维题
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6205 题意:给你n堆牌,原本每一堆的所有牌(a[i]张)默认向下,每次从第一堆开始,将固定个数的牌(b ...
- HDU 6198 2017沈阳网络赛 线形递推
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6198 题意:给出一个数k,问用k个斐波那契数相加,得不到的数最小是几. 解法:先暴力打表看看有没有规律 ...
- HDU 6201 2017沈阳网络赛 树形DP或者SPFA最长路
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6201 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过 ...
随机推荐
- 前端开发 Vue Vue.js和Nodejs的关系
首先vue.js 是库,不是框架,不是框架,不是框架. Vue.js 使用了基于 HTML 的模版语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据. Vue.js 的核心是一个允许你 ...
- [C#] 生成中文电子通讯录
var template = @" BEGIN:VCARD VERSION:2.1 N;CHARSET=gb2312:;{0};;; FN;CHARSET=gb2312:{0} TEL;CE ...
- Office 365 的安装与激活
(1)Office 365的安装,本处使用的是Office Tool Plus. (2)等待安装完成 (3)重头戏激活 , 使用命令行方式 (不推荐) 以下内容,新建文本文件,然后保存为.bat,再以 ...
- SAP开源的持续集成-持续交付的解决方案
SAP开源的持续集成/持续交付的解决方案: (1) 一个叫做piper的github项目,包含一个针对Jenkins的共享库和一个方便大家快速搭建CI/CD环境的Docker镜像: (2) 一套SAP ...
- 更新yum源并重建缓存
原文连接 1)下载wget yum install -y wget 2)备份默认的yum mv /etc/yum.repos.d /etc/yum.repos.d.backup 3)设置新的yum目录 ...
- 【转】国内CPU现状
首页 博客 学院 下载 图文课 论坛 APP CSDN CSDN学院 问答 商城 VIP会员 ...
- python中 "is"和"=="的区别
python中"is"和"=="区别 在做leetcode的时候,在判断两个数据是否相等时使用了python中的is not,想着入乡随俗,既然入了python ...
- Elasticsearch 术语介绍和CRUD实际操作入门
一.Elastic Stack 核心Elasticsearch Elasticsearch 是一个分布式.RESTful 风格的搜索和数据分析引擎.Elasticsearch 是面向文档的,这就意味着 ...
- node+express 搭建本地服务
首先,得有node环境,其次建个项目 目录例如 酱紫! 再次 写server.js,当然你可以换个名字a.js .b.js.why.js随你喜欢 var express = require('exp ...
- linux系统编程综合练习-实现一个小型的shell程序(二)
上节minishell当中,已经初步实现了一个简单命令的解析,这节来继续对更加复杂命令进行解析,包含:输入重定向的解析.管道行的解析.输出重定向的解析以及是否有后台作业的解析,如下: 下面对其进行实现 ...