【后缀自动机】hdu6194 string string string
题意:给你一个字符串和一个正整数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;
}
【后缀自动机】hdu6194 string string string的更多相关文章
- 【Hihocoder1413】Rikka with String(后缀自动机)
[Hihocoder1413]Rikka with String(后缀自动机) 题面 Hihocoder 给定一个小写字母串,回答分别把每个位置上的字符替换为'#'后的本质不同的子串数. 题解 首先横 ...
- 【计蒜客】是男人就过 8 题--Pony.AI 题 A. A String Game 后缀自动机+SG函数
[题目]A. A String Game [题意]给定目标串S和n个子串Ti,Alice和Bob轮流选择一个子串操作,必须且只能在子串末尾添加一个字符使得新串也是S的子串,不能操作即输,求胜利者.|S ...
- 2020牛客暑期多校训练营(第四场) C - Count New String (字符串,广义后缀自动机,序列自动机)
Count New String 题意: 定义字符串函数 \(f(S,x,y)(1\le x\le y\le n)\),返回一个长度为y-x+1的字符串,第 i 位是 \(max_{i=x...x+k ...
- 【hihocoder#1413】Rikka with String 后缀自动机 + 差分
搞了一上午+接近一下午这个题,然后被屠了个稀烂,默默仰慕一晚上学会SAM的以及半天4道SAM的hxy大爷. 题目链接:http://hihocoder.com/problemset/problem/1 ...
- BZOJ5408: string(广义后缀自动机,LCT)
传送门 解题思路: 首先在后缀树上,确定了一个节点就相当于确定了一个串,那么一个点对应的串在另外一个点对应的串产生贡献,当且仅当这个点在当前点子树内. 那么考虑一个新的点在串中对串答案的贡献在一条树链 ...
- 牛客多校第四场 I string 后缀自动机/回文自动机
这个回文自动机的板有问题,它虽然能过这道题,但是在计算size的时候会出锅! 题意: 求一个字符串中本质不同的连续子串有几个,但是某串和它反转后的字符串算一个. 题解: 要注意的是,一般字符串题中的“ ...
- <string> 与<string.h>、<cstring>的区别
<string.h> <string.h>是C版本的头文件,包含比如strcpy.strcat之类的字符串处理函数. <cstring> 在C++标准化(1998年 ...
- 再探Java基础——String.format(String format, Object… args)的使用
最近看到类似这样的一些代码:String.format("参数%s不能为空", "birthday"); 以前还没用过这功能不知咐意思,后研究了一下,详细讲解如 ...
- C/C++ - <string> 与<string.h>、<cstring>的区别
<string.h><string.h>是C版本的头文件,包含比如strcpy.strcat之类的字符串处理函数. <string><string>是C ...
- File(File f, String child) File(String parent, String child)
(转载)File(File f, String child) 根据f 抽象路径名和 child 路径名字符串创建一个新 File 实例. f抽象路径名用于表示目录,child 路径名字符串用于表示目录 ...
随机推荐
- Winform Socket通信
Socket相关概念[端口] 在Internet上有很多这样的主机,这些主机一般运行了多个服务软件,同时提供几种服务.每种服务都打开一个Socket,并绑定到一个端口上,不同的端口对应于不同的服务(应 ...
- 表格td内容超出宽度显示... table-layout: fixed;
td宽度用百分比固定好的时候,即使设置了 white-space:nowrap;/*文本不会换行,在同一行显示*/ overflow:hidden;超出隐藏 text-overflow:ellipsi ...
- 将资源文件夹中的文件通过流的方式写入到应用的File文件夹中
//1.在Files文件夹中创建同名的数据库文件 File files = getFilesDir(); File file = new File(files, DBName); if(file.ex ...
- BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 动态树
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2002 题意:加边,删边,查询到根的距离. #include <bits/stdc++ ...
- STL不同容器的使用方法
以下内容摘自:http://blog.csdn.net/u014465639/article/details/70241850 1.vector(需要导入头文件#include <vector& ...
- edittext 的一个案例
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android= ...
- HIbernate学习笔记4 之 延迟加载和 关联映射
一.延迟加载 * 在使用hibernate一些方法的查询数据的时候,返回的只是一个空对象(除id外属性都为NULL),并没有真正的查询数据库,而是在使用这个对象时才会触发查询数据库,并将这些数据注入到 ...
- python 函数内置方法short_desc
1. 给函数设置一个文本 def action_checked(self, request): pass action_checked.short_desc = "签到" # sh ...
- 《逐梦旅程 WINDOWS游戏编程之从零开始》笔记1——创建窗口&GDI
第1章 创建窗口 步骤: 窗口类的设计 窗口类的注册 窗口的正式创建 窗口的显示与更新 消息循环体系 窗口过程函数处理消息 1. 设计:使用WNDCLASSEX结构体,这里注意的是C++中的结构体中的 ...
- vue利用watch侦听对象具体的属性 ~ 巧用计算属性computed做中间层
有时候需要侦听某个对象具体的属性,可以按下面案例进行: <template> <div> <input type="text" v-model=&qu ...