Description

?? 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.

Input

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.

Output

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. 

Sample Input

2
a
abc
b
bbb

Sample Output

Case #1: 3
Case #2: 3

Hint

 

In 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.

 
思路:题目是给出一个串,求出这个串有多少个包含字符x的不同子串。首先考虑总的可能的方案数,对于每一个位置i,求出在它右边离她最近的字符x的位置p,那么这个位置贡献的答案就是n-p; 这样算出来的方案数显然会有重复,考虑去重。 我们对串求一遍后缀数组得到heigh数组,枚举heigh数组的每一个元素heigh[i],
即heigh[i] = LCP(sa[i-1],sa[i]);  如果在lcp这一段字符包含了x,且位置为pos,那么说明有lcp-pos个串重复了
 
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <cmath>
#include <vector>
#include <bitset>
#define ll long long
#define rep(x,to) for(int x=0;x<(to);x++)
#define repn(x,to) for(int x=1;x<=(to);x++)
#define clr(x) memset(x,0,sizeof(x))
#define pli pair<ll, int>
#define MEMSET(x,v) memset(x,v,sizeof(x))
#define pll pair<ll,ll>
#define pb push_back
#define MP make_pair
using namespace std;
const int N = 5e5 + ;
int t1[N], t2[N], c[N]; bool cmp(int *r, int a, int b, int l) {
return r[a] == r[b] && r[a+l] == r[b+l];
}
void da(int str[], int sa[], int Rank[], int heigh[], int n, int m) {
n++;
int i, j, p, *x = t1, *y = t2;
for(i = ; i < m; ++i) c[i] = ;
for(i = ; i < n; ++i) c[ x[i] = str[i] ]++;
for(i = ; i < m; ++i) c[i] += c[i - ];
for(i = n - ; i >= ; --i) sa[ --c[ x[i] ] ] = i; for(j = ; j <= n; j <<= ) { p = ;
for(i = n - j; i < n; ++i) y[p++] = i;
for(i = ; i < n; ++i) if(sa[i] >= j) y[p++] = sa[i] - j; 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];
swap(x, y);
p = ;
x[ sa[] ] = ;
for(i = ; i < n; ++i) x[ sa[i] ] = cmp(y, sa[i - ], sa[i], j) ? p - : p++;
if(p >= n) break;
m = p;
}
int k = ;
n--;
for(i = ; i <= n; ++i) Rank[ sa[i] ] = i;
for(i = ; i < n; ++i) {
if(k) k--;
j = sa[ Rank[i] - ];
while(str[i + k] == str[j + k]) k++;
heigh[ Rank[i] ] = k;
}
} int Rank[N], heigh[N];
char str[N];
int r[N];
int sa[N];
char X[];
int pre[N];
int pos[N];
int _ = ; void solve(int n) {
memset(pos, , sizeof pos);
int p = -;
ll sum = , num = ;
for(int i = n - ; i >= ; --i) {
if(str[i] == X[]) p = i;
pos[i] = p;
if(pos[i] != -) sum += (n - pos[i]);
}
//for(int i = 0; i < n; ++i) printf("%d ", pos[i]); for(int i = ; i <= n; ++i) { if(pos[ sa[i - ] ] == - || pos[ sa[i] ] == -) continue;
int c1 = pos[ sa[i - ] ] - sa[i - ] + ;
int c2 = pos[ sa[i] ] - sa[i] + ;
int h = heigh[i];
if(c1 > h || c2 > h) continue;
num += (h - c1 + );
}
printf("Case #%d: %I64d\n", _++, sum - num);
}
int main()
{
#ifdef LOCAL
freopen("in", "r", stdin);
#endif
int cas; scanf("%d", &cas);
while(cas --) {
scanf("%s%s", X, str);
int n = strlen(str);
for(int i = ; i < n; ++i) r[i] = str[i];
r[n] = ;
da(r, sa, Rank, heigh, n, ); solve(n);
// for(int i = 0; i < n; ++i) printf("%d ", Rank[i]); puts("");
// for(int i = 1; i <= n; ++i) printf("%d ", sa[i]); puts("");
// for(int i = 2; i <= n; ++i) printf("%d ", heigh[i]); puts("");
}
return ;
}

2016多校联合训练4 F - Substring 后缀数组的更多相关文章

  1. 2016多校联合训练1 D题GCD (ST表+二分)

    暑假颓废了好久啊...重新开始写博客 题目大意:给定10w个数,10w个询问.每次询问一个区间[l,r],求出gcd(a[l],a[l+1],...,a[r])以及有多少个区间[l',r']满足gcd ...

  2. 2016多校联合训练contest4 1012Bubble Sort

    Bubble Sort Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Tota ...

  3. 河南多校联合训练 F 不是匹配

    描述  有N个人,N个活动, 每个人只会对2个或者3个活动感兴趣,  每个活动也只有两个人或者两个活动对它兴趣,每个人参加一个  感兴趣的活动需要一天 ,且当天该活动被参加时,其他的人不能参加  如果 ...

  4. 2016多校联合训练1 B题Chess (博弈论 SG函数)

    题目大意:一个n(n<=1000)行,20列的棋盘上有一些棋子,两个人下棋,每回合可以把任意一个棋子向右移动到这一行的离这个棋子最近的空格上(注意这里不一定是移动最后一个棋子),不能移动到棋盘外 ...

  5. HDU6318-2018ACM暑假多校联合训练2-1010-Swaps and Inversions-树状数组

    本题题意是,给你一个长度为n的序列,使用最少的操作把序列转换为从小到大的顺序,并输出操作数*min(x,y) 实质上是算出该序列中有多少逆序对,有归并排序和树状数组两种算法,由于数据之间的差值有点大, ...

  6. hdu_1403_Longest Common Substring(后缀数组的应用)

    题目链接:hdu_1403_Longest Common Substring 题意: 给你两个字符串,然你找最长的公共子串 题解: 后缀数组的经典应用,要找两个字符串的公共子串,那么就相当于找两个串的 ...

  7. POJ3693 Maximum repetition substring [后缀数组 ST表]

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9458   Acc ...

  8. HDU 5769 Substring 后缀数组

    Substring Problem Description ?? is practicing his program skill, and now he is given a string, he h ...

  9. hdu 5769 Substring 后缀数组 + KMP

    http://acm.hdu.edu.cn/showproblem.php?pid=5769 题意:在S串中找出X串出现的不同子串的数目? 其中1 <= |S| < $10^5$ 官方题解 ...

随机推荐

  1. javac编译不同目录的源码提示找不到符号

    对于单个文件的且不引用其他类文件的java源码用javac编译大家都很熟悉即 javac mycode.java 但是如果这个文件引用到了其他的类文件,在进行编译的时候就会提示找不到符号,这时我们需要 ...

  2. window.onload =writeMessage(); 与window.onload =writeMessage;的区别

    window.onload =writeMessage(); window.onload =writeMessage; 异:第一种是window加载时执行writeMesage方法,第二种是把writ ...

  3. 手工配置rsyslog配置文件详解

    手工配置 如果您无法通过脚本生成配置文件,这份指导将帮助您通过简单的复制.粘贴手动完成配置. 假定您已拥有root或sudo权限,是在通用的Linux平台使用5.8.0或更高版本的rsyslog,rs ...

  4. 设计模式--桥接模式Bridge(结构型)

    一.概述 在软件系统中,某些类型由于自身的逻辑,它具有两个或者多个维度的变化,如何应对这种"多维度的变化",就可以利用桥接模式. 引例: 设想如果要绘制矩形.圆形.椭圆.正方形,我 ...

  5. cocos2d-js 学习笔记 --安装调试(2)

    对于初学者安装cocos2d-js的环境并没有教程中说的那么简单,至少笔者是这么认为的 第一步,下载cocos2d-js的SDK,(先别着急运行) 第二步,安装Cocos2d console ,(Ma ...

  6. SpringMVC

    使用注解去完成整个项目 安装spring的一个插件,则相关的提示就会出来

  7. 你不知道的Spring配置文件

    Spring配置文件是用于指导Spring工厂进行Bean生产.依赖关系注入(装配)及Bean实例分发的"图纸".Java EE程序员必须学会并灵活应用这份"图纸&quo ...

  8. WIN7凭据管理器保存的凭据过段时间会自动删除的解决办法

    控制面板\用户帐户和家庭安全\凭据管理器 进入该页面可看到所有凭据

  9. iOS系统验证关闭

    在浏览器上查看iOS系统与否方法:1.打开浏览器2.在地址栏中输入 ipsw.me3.在打开的网页中选择 Select a device 选择你要查看的设备型号:4.选择好设备之后点击select i ...

  10. AngularJS 路由

    AngularJS 路由允许我们通过不同的 URL 访问不同的内容. 通过 AngularJS 可以实现多视图的单页Web应用(single page web application,SPA). 通常 ...