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 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过 ...
随机推荐
- NIO开发Http服务器(3):核心配置和Request封装
最近学习了Java NIO技术,觉得不能再去写一些Hello World的学习demo了,而且也不想再像学习IO时那样编写一个控制台(或者带界面)聊天室.我们是做WEB开发的,整天围着tomcat.n ...
- java后台获取微信小程序openid
一.jar包准备 1.在网盘下载 链接:https://pan.baidu.com/s/15HAAWOg_yn768g4s9IrcPg 提取码:hgj0 二.在pom文件中添加依赖 1.将外部的引入的 ...
- 浅谈对BFC的认识,以及用bfc解决浮动问题
我们在前端的学习过程中常常会遇到BFC,用BFC来解决一些margin塌陷.margin合并清理浮动流的问题 那么问题来了,我们所说的BFC到底是个什么东西呢: 什么是BFC BFC(Block Fo ...
- Node笔记(新手入门必看)
. 初识Node.js 1.1 Node.js是什么 Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. ...
- RestFramework之序列化器源码解析
一.源码解析之序列化: 1.当视图类进行实例化序列化类做了如下操作: #ModelSerializer继承Serializer再继承BaseSerializer(此类定义实例化方法) #在BaseSe ...
- iOS 作为蓝牙外设广播信息
苹果蓝牙后台的限制,原本广播会有两个段分别是localName和serviceUUID这两块,但现在后台广播时,是不发送在这两段的 手机app可以作为一个蓝牙外设端来模拟外设硬件,但广播包里的数据只能 ...
- Android笔记(五十一) 短信验证码集成——mob平台
官方网站:www.mob.com 注册帐号,下载SDK,导入SDK就不说了,主要写一下简单集成如何使用,以后忘记了也可以翻着看看. 详细的可以参考官方文档: http://wiki.mob.com/a ...
- SQL Server 字段提取拼音首字母
目前工作中遇到一个情况,需要将SQL Server中的一个字段提取拼音的首字母,字段由汉字.英文.数字以及“-”构成,百度了一堆,找到如下方法,记录一下,以备后用! 首先建立一个函数 --生成拼音首码 ...
- git 常见的命令和错误
- selenium常用的API(三)获取网页title、html源码
获取网页title 获取页面title的方法可以直接用driver.title获取到,然后可以把获取到的结果用做断言. #encoding=utf-8 from selenium import web ...