题意:给你一个字符串和一个正整数K,让你输出恰好出现K次的子串的数量。

对后缀链接树进行dp预处理后,SAM每个点的endpos大小就是该点结尾的子串出现的次数,maxlen-minlen+1就是子串的数量,所以直接对endpos大小为K的点的(maxlen-minlen+1)求和即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXL 100000
#define MAXC 26
int v[2*MAXL+10],__next[2*MAXL+10],first[2*MAXL+10],e;
void AddEdge(int U,int V){
v[++e]=V;
__next[e]=first[U];
first[U]=e;
}
char s[MAXL+10];
int len;
struct SAM{
int endcnt[2*MAXL+10];
int n,maxlen[2*MAXL+10],minlen[2*MAXL+10],trans[2*MAXL+10][MAXC],slink[2*MAXL+10];
void clear(){
for(int i=0;i<=n;++i){
endcnt[i]=maxlen[i]=minlen[i]=slink[i]=first[i]=0;
memset(trans[i],0,sizeof(trans[i]));
}
n=e=0;
}
int new_state(int _maxlen,int _minlen,int _trans[],int _slink){
maxlen[n]=_maxlen;
minlen[n]=_minlen;
for(int i=0;i<MAXC;++i){
if(_trans==NULL){
trans[n][i]=-1;
}
else{
trans[n][i]=_trans[i];
}
}
slink[n]=_slink;
return n++;
}
int add_char(char ch,int u){
if(u==-1){
return new_state(0,0,NULL,-1);
}
int c=ch-'a';
int z=new_state(maxlen[u]+1,-1,NULL,-1);
endcnt[z]=1;
int v=u;
while(v!=-1 && trans[v][c]==-1){
trans[v][c]=z;
v=slink[v];
}
if(v==-1){
minlen[z]=1;
slink[z]=0;
return z;
}
int x=trans[v][c];
if(maxlen[v]+1==maxlen[x]){
minlen[z]=maxlen[x]+1;
slink[z]=x;
return z;
}
int y=new_state(maxlen[v]+1,-1,trans[x],slink[x]);
slink[y]=slink[x];
minlen[x]=maxlen[y]+1;
slink[x]=y;
minlen[z]=maxlen[y]+1;
slink[z]=y;
int w=v;
while(w!=-1 && trans[w][c]==x){
trans[w][c]=y;
w=slink[w];
}
minlen[y]=maxlen[slink[y]]+1;
return z;
}
void dfs(int U){
for(int i=first[U];i;i=__next[i]){
dfs(v[i]);
endcnt[U]+=endcnt[v[i]];
}
}
void work_slink_tree(){
for(int i=1;i<n;++i){
AddEdge(slink[i],i);
}
dfs(0);
}
}sam;
int anss[MAXL+10];
int T,K;
typedef long long ll;
int main(){
// freopen("a.in","r",stdin);
scanf("%d",&T);
for(;T;--T){
scanf("%d%s",&K,s);
len=strlen(s);
int U=sam.add_char(0,-1);
for(int i=0;i<len;++i){
U=sam.add_char(s[i],U);
}
sam.work_slink_tree();
ll ans=0;
for(int i=1;i<sam.n;++i){
if(sam.endcnt[i]==K){
ans+=(ll)(sam.maxlen[i]-sam.minlen[i]+1);
}
}
printf("%d\n",ans);
sam.clear();
}
return 0;
}

最新文章

  1. iframe关于滚动条的去除和保留
  2. C# DataGrid合并单元格
  3. Oracle数据库初级学习 2
  4. 计算webView的 高度 和自适应屏幕大小
  5. NotImplementedException未实现该方法或操作
  6. ProductHunt:创业公司产品猎场和秀场
  7. Git命令行和Xcode结合使用
  8. (转)Linux(Centos)之安装Java JDK及注意事项
  9. Spring4 customEditors
  10. 动态加载js css 插件
  11. 游戏AI-行为树理论及实现
  12. 《Thinking in Java》学习笔记(一)
  13. H5移动端rem适配
  14. __x__(44)0910第六天__表单
  15. 福州大学软件工程1816 | W班 第1次作业成绩排名
  16. OEM、ODM、OBM、OPM概念,作用与区别
  17. Oracle PLSQL Demo - 09.Open、Fetch遍历游标[Open, Fetch, Close Record CURSOR]
  18. [BZOJ 5323][Jxoi2018]游戏
  19. web三大组件的加载顺序
  20. swagger接口变动监控

热门文章

  1. 爬虫--BeautifulSoup
  2. Warning: File upload error - unable to create a temporary file in Unknown on line 0
  3. webpack自动生成项目的html
  4. linux安装(Ubuntu)——(二)
  5. 【转】bmp文件格式详解
  6. 初识费用流 模板(spfa+slf优化) 餐巾计划问题
  7. vue路由-动态路由和嵌套路由
  8. linux irq 自动探测
  9. Redis 主从部署
  10. 【2017 Multi-University Training Contest - Team 1】小结