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 题意:给出一棵树,每个点有一个权值,代表商品的售价,树上每一条边上也有一个权值,代表从这条边经过 ...
随机推荐
- PLSQL登录失败出现空白错误提示框的问题
安装win7后其他软件运行正常,可是数据库用cmd plsplus和plsql软件都连不上,plsql报一个空白提示框 重装n遍oracle客户端,都不行. 最后发现解决方式很简单,在plsql的图标 ...
- 关于Eclipse导入maven项目报空指针异常
今天新建了一个maven项目,因为是通过公司的工具新建的,代码拉下来就有src.pom.xml文件. 导入Eclipse却报空指针异常.具体如下: An error has occurred. See ...
- mysql 存储过程、视图---创建、调用、删除
之前一直用的是Sql Server数据库,最近偶然机会接触到mysql.这里总结了关于mysql 存储过程.视图的“创建.调用.删除”示例 ============================== ...
- pssh安装及使用
pssh全称是parallel-ssh,基于Python编写的并发在多台服务器上批量执行命令的工具,它支持文件并行复制.远程并行执行命令.杀掉远程主机上的进程等:该工具可以视作ansible的简化版本 ...
- SQL月度统计
select Convert ( VARCHAR(7),CreateTime,120) as Date ,sum(Money) as M FROM [LBAmmeterDB].[dbo].Am_Tas ...
- 在LINUX下ORACLE11.2.04的安装脚本及静默安装
首先写好配置环境脚本 cd /opt vi oraclesetup #!/bin/bashecho "back file to filebackup"mkdir -p /opt/f ...
- 批处理引擎MapReduce程序设计
批处理引擎MapReduce程序设计 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.MapReduce API Hadoop同时提供了新旧两套MapReduce API,新AP ...
- css详解1
1.css的三种引入方式: 1.1.行内引入 <div style="color:red;">魔降风云变</div> <html> <he ...
- XML DOM 知识点
第一部分[DOM基础] DOM介绍: 1.什么是 HTML DOM? HTML DOM 定义了所有 HTML 元素的对象和属性,以及访问它们的方法(接口). 2.什么是 XML DOM? XML DO ...
- Springboot的 get查看,post创建,put更新,delete删除 -四种请求实例(form + controller)
总结 --get查看数据, post创建新数据行, put更新数据, delete删除数据行-- add和select功能都共用这一个页面, 需要进行区分显示 ,使用thymeleaf的三元选择,判断 ...