Hdu-5769 Substring (SA后缀数组)
2016-07-29 21:43
435 查看
Substring
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 485 Accepted Submission(s): 202
[align=left]Problem Description[/align]
?? is practicing his program skill, and now he is given a string, he has to calculate the total number of its distinct substrings.
But ?? thinks that is too easy, he wants to make this problem more interesting.
?? likes a character X very much, so he wants to know the number of distinct substrings which contains at least one X.
However, ?? is unable to solve it, please help him.
[align=left]Input[/align]
The first line of the input gives the number of test cases T;T test cases follow.
Each test case is consist of 2 lines:
First line is a character X, and second line is a string S.
X is a lowercase letter, and S contains lowercase letters(‘a’-‘z’) only.
T<=30
1<=|S|<=10^5
The sum of |S| in all the test cases is no more than 700,000.
[align=left]Output[/align]
For each test case, output one line containing “Case #x: y”(without quotes), where x is the test case number(starting from 1) and y is the answer you get for that case.
[align=left]Sample Input[/align]
2
a
abc
b
bbb
[align=left]Sample Output[/align]
Case #1: 3
Case #2: 3
HintIn first case, all distinct substrings containing at least one a: a, ab, abc.
In second case, all distinct substrings containing at least one b: b, bb, bbb.
题意:给你一个字符和一个字符串,问你字符串中包含这个字符的不同子串的个数。
分析:求出所有后缀后边最近的要求字符的位置f[i],对于后缀sa[i],对答案的贡献就是n - max(sa[i]+height[i],f[sa[i]])。
#include<iostream>
#include<string>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<set>
#include<map>
#include<vector>
#include<cstring>
#include<stack>
#include<cmath>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
//rank从0开始
//sa从1开始,因为最后一个字符(最小的)排在第0位
//height从2开始,因为表示的是sa[i-1]和sa[i]
const int MAXN = 100005;
int T,n,m,Rank[MAXN],sa[MAXN],X[MAXN],Y[MAXN],height[MAXN],s[MAXN],f[MAXN];
int buc[MAXN];
char str[MAXN],C[2];
void calheight(int n)
{
int i , j , k = 0;
for(i = 1 ; i <= n ; i++) Rank[sa[i]] = i;
for(i = 0 ; i < n ; height[Rank[i++]] = k)
for(k?k--:0 , j = sa[Rank[i]-1] ; s[i+k] == s[j+k] ; k++);
}
bool cmp(int *r,int a,int b,int l)
{
return (r[a] == r[b] && r[a+l] == r[b+l]);
}
void suffix(int n,int m = 128)
{
int i , l , p , *x = X , *y = Y;
for(i = 0 ; i < m ; i ++) buc[i] = 0;
for(i = 0 ; i < n ; i ++) buc[ x[i] = s[i] ] ++;
for(i = 1 ; i < m ; i ++) buc[i] += buc[i-1];
for(i = n - 1; i >= 0 ; i --) sa[ --buc[ x[i] ]] = i;
for(l = 1,p = 1 ; p < n ; m = p , l *= 2)
{
p = 0;
for(i = n-l ; i < n ; i ++) y[p++] = i;
for(i = 0 ; i < n ; i ++) if(sa[i] >= l) y[p++] = sa[i] - l;
for(i = 0 ; i < m ; i ++) buc[i] = 0;
for(i = 0 ; i < n ; i ++) buc[ x[y[i]] ] ++;
for(i = 1 ; i < m ; i ++) buc[i] += buc[i-1];
for(i = n - 1; i >= 0 ; i --) sa[ --buc[ x[y[i]] ] ] = y[i];
for(swap(x,y) , x[sa[0]] = 0 , i = 1 , p = 1 ; i < n ; i ++)
x[ sa[i] ] = cmp(y,sa[i-1],sa[i],l) ? p-1 : p++;
}
calheight(n-1);//后缀数组关键是求出height,所以求sa的时候顺便把rank和height求出来
}
int main()
{
scanf("%d",&T);
for(int t = 1;t <= T;t++)
{
scanf("%s",C);
scanf("%s",str);
int n = strlen(str);
for(int i = 0;i < n;i++) s[i] = str[i];
s
= 0;
int now = n;
for(int i = n-1;i >= 0;i--)
{
if(str[i] == C[0]) now = i;
f[i] = now;
}
suffix(n+1,128);
long long tot = 1ll*n - max(sa[1],f[sa[1]]);
for(int i = 2;i <= n;i++)
tot += 1ll*n - max(sa[i]+height[i],f[sa[i]]);
printf("Case #%d: %I64d\n",t,tot);
}
}
相关文章推荐
- 【cdoj 1325】卿学姐与基本法 离散化+线段树
- Spring3核心技术之事务管理机制(转载)
- iOS开源照片浏览器框架SGPhotoBrowser的设计与实现
- 优雅地实现Android Toolbar及沉浸式状态栏
- dvm和jvm都是什么东西,有什么区别?
- IDEA常用快捷键 XShell常用快捷键
- Leetcode Kth Largest Element in an Array
- PAT-A 1004. Counting Leaves (30) (树)
- 003——Bean的作用域
- HDOJ 2612 Find a way【BFS】
- 【VMCloud云平台】拥抱Docker(六)关于DockerFile(3)示例
- 【VMCloud云平台】拥抱Docker(六)关于DockerFile(3)示例
- BZOJ 2467 解题报告
- BZOJ 2467 解题报告
- Lnmp架构之MYSQL
- UVA 12034 Race
- Linux strace 命令用法详解:跟踪系统调用和信号
- SICP_Python版本:Hufuman编码
- 五种排序方法(选择、冒泡、快排、插入、希尔)
- CSS 之 overflow