CodeForces-204E:Little Elephant and Strings (广义后缀自动机求出现次数)
The Little Elephant loves strings very much.
He has an array a from n strings, consisting of lowercase English letters. Let's number the elements of the array from 1 to n, then let's denote the element number i as ai. For each string ai (1 ≤ i ≤ n) the Little Elephant wants to find the number of pairs of integers l and r (1 ≤ l ≤ r ≤ |ai|) such that substring ai[l... r] is a substring to at least k strings from array a (including the i-th string).
Help the Little Elephant solve this problem.
If you are not familiar with the basic notation in string problems, you can find the corresponding definitions in the notes.
Input
The first line contains two space-separated integers — n and k (1 ≤ n, k ≤ 105). Next n lines contain array a. The i-th line contains a non-empty string ai, consisting of lowercase English letter. The total length of all strings ai does not exceed 105.
Output
On a single line print n space-separated integers — the i-th number is the answer for string ai.
Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.
Example
3 1
abc
a
ab
6 1 3
7 4
rubik
furik
abab
baba
aaabbbababa
abababababa
zero
1 0 9 9 21 30 0
题意:给定N和L,输入N个字符串,对于每个字符串,输出其有多少个字串满足在这N个串里出现的次数大于等于K。
思路:广义后缀自动机模板题,或者后缀数组。
注意:注意K>N时直接输出若干个0,不然会超时,GG。
向上传递时我大胆的试了一试Bitset,结果超内存了。但是set没问题。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=;
int N,K,L,times; string s[maxn];
struct SAM
{
int np,p,nq,q,Last,cnt,cur[maxn],sum[maxn];
int maxlen[maxn],fa[maxn],ch[maxn][];
SAM(){ Last=cnt=; }
void add(int x){
np=++cnt; p=Last; Last=np; maxlen[np]=maxlen[p]+;
while(p&&!ch[p][x]) ch[p][x]=np,p=fa[p];
if(!p) fa[np]=;
else{
q=ch[p][x];
if(maxlen[q]==maxlen[p]+) fa[np]=q;
else{
nq=++cnt;
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
cur[nq]=cur[q]; sum[nq]=sum[q];
fa[nq]=fa[q]; fa[np]=fa[q]=nq;maxlen[nq]=maxlen[p]+;
while(p&&ch[p][x]==q) ch[p][x]=nq,p=fa[p];
}
}
while(np){
if(cur[np]==times||sum[np]>=K) break;
sum[np]++; cur[np]=times; np=fa[np];
}
}
void sort()
{ }
void solve(int now)
{
int tp=;long long ans=; L=s[now].length();
for(int i=;i<L;i++) {
tp=ch[tp][s[now][i]-'a'];
int kkk=tp;
while(kkk>){
if(sum[kkk]>=K){ ans+=maxlen[kkk]; break; }
kkk=fa[kkk];
}
}
printf("%lld ",ans);
}
}sam;
int main()
{
scanf("%d%d",&N,&K);
for(int i=;i<=N;i++){
cin>>s[i];
L=s[i].length(); sam.Last=; times=i;
for(int j=;j<L;j++) sam.add(s[i][j]-'a');
}
if(K>N){
for(int i=;i<=N;i++) printf("0 ");
return ;
}
sam.sort();
for(int i=;i<=N;i++) sam.solve(i);
return ;
}
拓扑后set传递。
#include<set>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=;
int N,K,times; char s[maxn];
set<int>Set[maxn];
int a[maxn],b[maxn],sum[maxn],L[maxn],R[maxn];
struct SAM
{
int np,p,nq,q,Last,cnt,maxlen[maxn],fa[maxn],ch[maxn][];
SAM(){ Last=cnt=; }
void add(int x){
np=++cnt; p=Last; Last=np; maxlen[np]=maxlen[p]+;
while(p&&!ch[p][x]) ch[p][x]=np,p=fa[p];
if(!p) fa[np]=;
else{
q=ch[p][x];
if(maxlen[q]==maxlen[p]+) fa[np]=q;
else{
nq=++cnt;
memcpy(ch[nq],ch[q],sizeof(ch[nq]));
fa[nq]=fa[q]; fa[np]=fa[q]=nq;maxlen[nq]=maxlen[p]+;
while(p&&ch[p][x]==q) ch[p][x]=nq,p=fa[p];
}
}
}
void sort()
{
for(int i=;i<=cnt;i++) a[maxlen[i]]++;
for(int i=;i<=cnt;i++) a[i]+=a[i-];
for(int i=;i<=cnt;i++) b[a[maxlen[i]]--]=i;
for(int i=;i<=N;i++){
int tp=;
for(int j=L[i];j<=R[i];j++){
tp=ch[tp][s[j]-'a'];
Set[tp].insert(i);
}
}
for(int i=cnt;i>;i--){
int x=b[i];
sum[x]=Set[x].size();
int y=fa[x];
if(Set[x].size()>Set[y].size()) swap(Set[x],Set[y]);
for(set<int>::iterator it=Set[x].begin();it!=Set[x].end();it++)
Set[y].insert(*it);
}
}
void solve(int now)
{
int tp=; long long ans=;
for(int i=L[now];i<=R[now];i++) {
tp=ch[tp][s[i]-'a'];
int kkk=tp;
while(kkk>){
if(sum[kkk]>=K){ ans+=maxlen[kkk];break;}
kkk=fa[kkk];
}
}
printf("%lld ",ans);
}
}sam;
int main()
{
scanf("%d%d",&N,&K);
for(int i=;i<=N;i++){
L[i]=R[i-]+;
scanf("%s",s+L[i]);
R[i]=L[i]+strlen(s+L[i])-;
sam.Last=;
for(int j=L[i];j<=R[i];j++) sam.add(s[j]-'a');
}
if(K>N){
for(int i=;i<=N;i++) printf("0 ");
return ;
}
sam.sort();
for(int i=;i<=N;i++) sam.solve(i);
return ;
}
CodeForces-204E:Little Elephant and Strings (广义后缀自动机求出现次数)的更多相关文章
- codeforces 204E. Little Elephant and Strings(广义后缀自动机,Parent树)
传送门在这里. 大意: 给一堆字符串,询问每个字符串有多少子串在所有字符串中出现K次以上. 解题思路: 这种子串问题一定要见后缀自动机Parent树Dfs序统计出现次数都是套路了吧. 这道题统计子串个 ...
- [Codeforces 204E] Little Elephant and Strings
[题目链接] https://codeforces.com/contest/204/problem/E [算法] 首先构建广义后缀自动机 对于自动机上的每个节点 , 维护一棵平衡树存储所有它所匹配的字 ...
- E. Three strings 广义后缀自动机
http://codeforces.com/problemset/problem/452/E 多个主串的模型. 建立一个广义后缀自动机,可以dp出每个状态的endpos集合大小.同时也维护一个R[]表 ...
- CF452E Three strings 广义后缀自动机
建一个广义后缀自动机统计一下就行,好长时间不敲后缀自动机调了半天~ #include <bits/stdc++.h> using namespace std; namespace IO { ...
- MemSQL Start[c]UP 2.0 - Round 1 E - Three strings 广义后缀自动机
E - Three strings 将三个串加进去,看每个节点在三个串中分别出现了多少次. #include<bits/stdc++.h> #define LL long long #de ...
- CF 666E Forensic Examination——广义后缀自动机+线段树合并
题目:http://codeforces.com/contest/666/problem/E 对模式串建广义后缀自动机,询问的时候把询问子串对应到广义后缀自动机的节点上,就处理了“区间”询问. 还要处 ...
- D. Match & Catch 后缀自动机 || 广义后缀自动机
http://codeforces.com/contest/427/problem/D 题目是找出两个串的最短公共子串,并且在两个串中出现的次数只能是1次. 正解好像是dp啥的,但是用sam可以方便很 ...
- POJ3080 POJ3450Corporate Identity(广义后缀自动机||后缀数组||KMP)
Beside other services, ACM helps companies to clearly state their “corporate identity”, which includ ...
- SPOJ8093Sevenk Love Oimaster(广义后缀自动机)
Oimaster and sevenk love each other. But recently,sevenk heard that a girl named ChuYuXun was da ...
随机推荐
- SkyWalking 分布式追踪系统
随着微服务架构的流行,一些微服务架构下的问题也会越来越突出,比如一个请求会涉及多个服务,而服务本身可能也会依赖其他服务,整个请求路径就构成了一个网状的调用链,而在整个调用链中一旦某个节点发生异常,整个 ...
- CodeForces - 750B New Year and North Pole
http://codeforces.com/problemset/problem/750/B 模拟题 审题 在南极点 只能向北走(不能向 南 东 西) 所以也就不存在走过南极点的情况 北极点同样 然后 ...
- 使用imageMagick 制作圆角矩形和图片加水印
制作圆角矩形好图片水印都是图片合成的操作 composite -gravity southeast mask175.png src.jpg dest.jpg -gravity southeast ...
- 动态规划:HDU1087Super Jumping! Jumping! Jumping!(最大上升和)
Problem Description Nowadays, a kind of chess game called “Super Jumping! Jumping! Jumping!” is very ...
- C语言取整方法总结
C语言有下面几种取整方法: 1. 直接赋值给整数变量 int i = 3.5; 或 i = (int) 3.5; 这样的方法採用的是舍去小数部分. 2.整数除法运算符' / '取整 ' / ...
- CentOS 5 全功能服务器搭建
转自: http://www.php-oa.com/2007/12/27/centos-www.html 转:主要做为历史记录,以后用.另外很少见这么好的编译的文章,其实我不推荐用编译安装.但这个文章 ...
- Win7 丢失MSVCR110.DLL的解决办法
1 从下面的网站下载dll文件 http://www.ddooo.com/softdown/27034.htm 2 把该文件放到C:\Windows\SysWOW64目录下(64位系统)或者C:\ ...
- vux-uploader 图片上传组件
1.网址:https://github.com/greedying/vux-uploader 2.安装 npm install vux-uploader --save npm install --sa ...
- React Native入门——布局实践:开发京东client首页(一)
有了一些对React Native开发的简单了解,让我们从实战出发.一起来构建一个简单的京东client. 这个client是仿照之前版本号的京东client开发的Android版应用,来源于CSDN ...
- CALayer与UIView的关系
CALayer属于Core Animation部分的内容,比较重要而不太好理解.以下是园子中看到的一篇文章的摘录: 1. UIView是iOS系统中界面元素的基础,所有的界面元素都是继承自它.它本身完 ...