|spoj 694|后缀数组|Distinct Substrings
spoj 694
给出一个字符串,求字符串中不相同的子串个数。
我们可以知道,字符串中的每个子串都是某个后缀的前缀,于是题目转化为求不相同的后缀的前缀问题。对于每一个SA[k]SA[k]开始的后缀,将会增加n−SA[k]+1n-SA[k]+1个后缀,而其中height[k]height[k]个是和前面的字符串的前缀是相同的。所以答案就是所有n−SA[k]+1−height[k]n-SA[k]+1-height[k]的总和
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ms(i, j) memset(i, j, sizeof i)
#define FN2 "spoj694"
using namespace std;const int MAXN = 1000 + 5;char s[MAXN];
int n, m, a[MAXN], tp[MAXN], rk[MAXN], SA[MAXN], tax[MAXN], height[MAXN];bool cmp(int *f, int i, int k) {return f[SA[i]]==f[SA[i-1]]&&f[SA[i]+k]==f[SA[i-1]+k];}
void build() {for (int i=0;i<m;i++) tax[i] = 0;for (int i=0;i<n;i++) tax[rk[i]=a[i]]++;for (int i=1;i<m;i++) tax[i] += tax[i-1];for (int i=n-1;i>=0;i--) SA[--tax[rk[i]]] = i;int p;for (int k=1;k<=n;k*=2) {p = 0;for (int i=n-k;i<n;i++) tp[p++] = i;for (int i=0;i<n;i++) if (SA[i]>=k) tp[p++] = SA[i]-k;for (int i=0;i<m;i++) tax[i] = 0;for (int i=0;i<n;i++) tax[rk[tp[i]]]++;for (int i=1;i<m;i++) tax[i] += tax[i-1];for (int i=n-1;i>=0;i--) SA[--tax[rk[tp[i]]]] = tp[i];swap(rk, tp), p = 0, rk[SA[0]] = 0;for (int i=1;i<n;i++) rk[SA[i]] = cmp(tp, i, k) ? p : ++p;if (++p>=n) break;m = p;}
}
void getH() {int k = 0;for (int i=0;i<n;i++) {if (k) k--;int j = SA[rk[i]-1];while (a[i+k]==a[j+k]) k++;height[rk[i]] = k;}
}
void init() {scanf("%s", s);n = strlen(s) + 1;for (int i=0;i<n-1;i++) a[i] = s[i];m = 128, a[n-1] = 0;
}
void solve() {build(), getH();int ans = 0;for (int i=1;i<n;i++) {ans += (n-1) - SA[i] - height[i];}printf("%d\n", ans);
}
int main() {#ifndef ONLINE_JUDGEfreopen(FN2".in","r",stdin);freopen("1.out","w",stdout);#endifint kase; scanf("%d", &kase);while(kase--) init(), solve();return 0;
}
|spoj 694|后缀数组|Distinct Substrings相关推荐
- New Distinct Substrings(后缀数组)
New Distinct Substrings(后缀数组) 给定一个字符串,求不相同的子串的个数.\(n<=50005\). 显然,任何一个子串一定是后缀上的前缀.先(按套路)把后缀排好序,对于 ...
- SPOJ 220 Relevant Phrases of Annihilation(后缀数组+二分答案)
[题目链接] http://www.spoj.pl/problems/PHRASES/ [题目大意] 求在每个字符串中出现至少两次的最长的子串 [题解] 注意到这么几个关键点:最长,至少两次,每个字符 ...
- SPOJ 7258 SUBLEX 后缀数组_二分答案_前缀和
SPOJ 7258 SUBLEX 后缀数组_二分答案_前缀和 Code: #include <cstdio> #include <algorithm> #include < ...
- CSU1632Repeated Substrings(后缀数组/最长公共前缀)
题意就是求一个字符串的重复出现(出现次数>=2)的不同子串的个数. 标准解法是后缀数组.最长公共前缀的应用,对于样例aabaab,先将所有后缀排序: aab 3 aabaab 1 a ...
- SPOJ - PHRASES Relevant Phrases of Annihilation —— 后缀数组 出现于所有字符串中两次且不重叠的最长公共子串...
题目链接:https://vjudge.net/problem/SPOJ-PHRASES PHRASES - Relevant Phrases of Annihilation no tags You ...
- POJ1226 Substrings(二分+后缀数组)
题意:给n个字符串,求最长的子串,满足它或它的逆置出现在所有的n个字符串中. 把n个字符串及其它们的逆置拼接,中间用不同字符隔开,并记录suffix(i)是属于哪个字符串的: 跑后缀数组计算heigh ...
- POJ - 3415 Common Substrings(后缀数组+单调栈)
题目链接:点击查看 题目大意:给出两个字符串,再给出一个k,问两个字符串中长度大于等于k的公共子串有多少个(种类可重复) 题目分析:因为涉及到了子串问题,先用后缀数组跑出height数组来,接下来如果 ...
- 【2012百度之星/资格赛】H:用户请求中的品牌 [后缀数组]
时间限制: 1000ms 内存限制: 65536kB 描述 馅饼同学是一个在百度工作,做用户请求(query)分析的同学,他在用户请求中经常会遇到一些很奇葩的词汇.在比方说"johnsonj ...
- HDU 5769 Substring(后缀数组)
Substring Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Total ...
最新文章
- 数据驱动:新药物发现知识图
- 3句话概括 PUT/POST 的区别
- NAND Flash和NOR Flash的区别
- 大讲台大数据特训学习笔记
- IOS 程序猿 UITbleView 篇
- android 蓝牙设置平板电脑,java – BlueCove,笔记本电脑和带蓝牙的Android平板电脑
- oracle 数据库,用户管理以及表空间等相关基础操作
- Android APK反编译就这么简单 详解
- 计算机活动宣传稿,畅想科技,创造梦想 ——东华大学计算机科学与技术学院第十一届图灵科技文化节通讯稿...
- 深层神经网络——分类、回归的损失函数
- java中常量有初始化值吗,Java基础_变量、常量
- 从零开始实现 AlphaGo(一)
- 2021年dedecms伪原创插件,织梦AI文章伪原创插件使用方法
- 【论文笔记】AutoML: A survey of the state-of-the-art(下篇)
- CyanogenMod 和 Cyanogen OS 对比
- 如何在 AWS 云中从 Amazon EC2 启动 RHEL 8?
- 利用python识别身份证号后获取年龄和性别信息
- xv6 6.S081 Lab3: alloc
- Python argparse.ArgumentParser的add_argument()用法
- 联想涉密专用计算机 字体,Lenovo出厂高分屏笔记本高分辨率下字体模糊的解决方法...
热门文章
- wc 一个进程结果是2_用开放的wc创建一个Web组件
- 皮马印第安人糖尿病数据集分享
- FFMPEG 压缩视频文件
- 借一道leetcode思考总结map/set的应用及区别
- mysql 5.7.17 zip_win10下mysql 5.7.17 zip压缩包版安装教程
- 如何让google,baidu,Yahoo收录你的网站
- 2022-05-25 网工进阶(七)OSPF-影响邻居关系建立的因素、路由撤销、路由汇总、路由过滤、Silent-Interface、报文认证
- IMM管理口收集日志
- linux连接oracle的日志,linux shell脚本连接oracle查询数据插入文件和日志文件中
- Numpy API 速查表