http://acm.hdu.edu.cn/showproblem.php?pid=4641

http://acm.hdu.edu.cn/showproblem.php?pid=6194

题意: 开始时给出一个字符串,给出两种操作,一种是在字符串后面添加一个字符,
另一个是查询出现过最少出现K次的字串个数。

分析:

建立后缀自动机,添加一个字符插入即可,对于查询,前面计算过的没必要再算,
直接从当前开始往前面找,已经达到K次的就不管,说明前面已经计算过,现在达到
K次的加进答案。

#include<bits/stdc++.h>
using namespace std;
#define mem(a , b) memset(a , b , sizeof(a))
const int maxn = ;
#define ll long long struct SAM{
int trans[maxn<<][] , slink[maxn<<] , maxlen[maxn<<];
int last , now , root;
ll ans=;
int sum[maxn<<];
void newnode(int v)
{
maxlen[++now]=v;
mem(trans[now],); }
void extend(int c , int k)
{
newnode(maxlen[last] + );
int p = last , np = now;sum[now]=;
// cout<<now<<endl;
while(p && !trans[p][c])
{
trans[p][c] = np;
p = slink[p];
}
if(!p) slink[np] = root;
else
{
int q = trans[p][c];
if(maxlen[p] + != maxlen[q])
{
newnode(maxlen[p] + );
int nq = now;
memcpy(trans[nq] , trans[q] , sizeof(trans[q]));
sum[nq]=sum[q];///分开的节点要继承
slink[nq] = slink[q];
slink[q] = slink[np] = nq;
while(p && trans[p][c] == q)
{
trans[p][c] = nq;
p = slink[p];
}
}
else
{
slink[np]=q;
}
}
last = np;
int w=np;
while(w && sum[w] < k )
{
sum[w]++;
if(sum[w]==k) ans+=maxlen[w]-maxlen[slink[w]];
w=slink[w];
}
// cout<<np<<endl;
}
void init()
{
root = last = now = ;
slink[root]=;
mem(trans[root],);
sum[root]=;
ans=;
} }sam;
int main()
{ int n,q,k;
while(scanf("%d%d%d",&n,&q,&k)!=EOF){
sam.init();
char str[maxn];scanf("%s",str);
for(int i= ; i<n ; i++)
{
sam.extend(str[i]-'a' , k);
}
while(q--)
{
int T;scanf("%d",&T);
getchar(); if(T==)
{ char op;
op=getchar();
sam.extend(op-'a' , k );
// cout<<op<<endl;
}
else
{
printf("%lld\n",sam.ans);
}
}
} }

关于恰好出现k次的字符串 , 我们只要求出至少k次的字串 - 至少(k+1)次的字串 ,不恰好就是k次吗

#include<bits/stdc++.h>
using namespace std;
#define mem(a , b) memset(a , b , sizeof(a))
const int maxn = ;
#define ll long long struct SAM{
int trans[maxn<<][] , slink[maxn<<] , maxlen[maxn<<];
int last , now , root;
ll ans=;
int sum[maxn<<];
void newnode(int v)
{
maxlen[++now]=v;
mem(trans[now],); }
void extend(int c , int k)
{
newnode(maxlen[last] + );
int p = last , np = now;sum[now]=;
// cout<<now<<endl;
while(p && !trans[p][c])
{
trans[p][c] = np;
p = slink[p];
}
if(!p) slink[np] = root;
else
{
int q = trans[p][c];
if(maxlen[p] + != maxlen[q])
{
newnode(maxlen[p] + );
int nq = now;
memcpy(trans[nq] , trans[q] , sizeof(trans[q]));
sum[nq]=sum[q];///分开的节点要继承
slink[nq] = slink[q];
slink[q] = slink[np] = nq;
while(p && trans[p][c] == q)
{
trans[p][c] = nq;
p = slink[p];
}
}
else
{
slink[np]=q;
}
}
last = np;
int w=np;
while(w && sum[w] < k )
{
sum[w]++;
if(sum[w]==k) ans+=maxlen[w]-maxlen[slink[w]];
w=slink[w];
}
// cout<<np<<endl;
}
void init()
{
root = last = now = ;
slink[root]=;
mem(trans[root],);
sum[root]=;
ans=;
} }sam;
int main()
{ int n,q,k;
int t;scanf("%d",&t);
while(t--)
{ string str;int k;
cin>>k>>str;
sam.init();
n=str.size();
for(int i= ; i<n ; i++)
{
sam.extend(str[i]-'a' , k);
}
ll sum1=sam.ans;
sam.init();
for(int i= ; i<n ; i++)
{
sam.extend(str[i]-'a' , k+);
}
ll sum2=sam.ans;
printf("%lld\n",sum1-sum2);
} }

HDU4641 || 6194多校 (后缀自动机-最少出现K次的字串个数 || 恰好出现K次字符串的个数)的更多相关文章

  1. SPOJ 1811 Longest Common Substring (后缀自动机第一题,求两个串的最长公共子串)

    题目大意: 给出两个长度小于等于25W的字符串,求它们的最长公共子串. 题目链接:http://www.spoj.com/problems/LCS/ 算法讨论: 二分+哈希, 后缀数组, 后缀自动机. ...

  2. CodeForces-427D:Match & Catch (后缀自动机)

    Police headquarter is monitoring signal on different frequency levels. They have got two suspiciousl ...

  3. 2019牛客多校第四场 I题 后缀自动机_后缀数组_求两个串de公共子串的种类数

    目录 求若干个串的公共子串个数相关变形题 对一个串建后缀自动机,另一个串在上面跑同时计数 广义后缀自动机 后缀数组 其他:POJ 3415 求两个串长度至少为k的公共子串数量 @(牛客多校第四场 I题 ...

  4. 【算法】后缀自动机(SAM) 初探

    [自动机] 有限状态自动机的功能是识别字符串,自动机A能识别字符串S,就记为$A(S)$=true,否则$A(S)$=false. 自动机由$alpha$(字符集),$state$(状态集合),$in ...

  5. 一文读懂后缀自动机 Suffix_Automata

    原论文(俄文)地址:suffix_automata 原翻译(中文)地址:后缀自动机详解(DZYO的博客) Upd:强推浅显易懂(?)的SAM讲解 后缀自动机 后缀自动机(单词的有向无环图)--是一种强 ...

  6. 『后缀自动机入门 SuffixAutomaton』

    本文的图片材料多数来自\(\mathrm{hihocoder}\)中详尽的\(SAM\)介绍,文字总结为原创内容. 确定性有限状态自动机 DFA 首先我们要定义确定性有限状态自动机\(\mathrm{ ...

  7. Codechef2015 May - Chef and Strings (后缀自动机)

    用后缀自动机统计出出现1~n次的串的数量f[i] 对于ans[k]=sigma(f[i]*C(i,k)) i>=k ; mo=; ..maxn] of dword; nt:..maxn,'a'. ...

  8. hdu4641-K-string(后缀自动机)

    Problem Description Given a string S. K-string is the sub-string of S and it appear in the S at leas ...

  9. spoj 1812 lcsII (后缀自动机)

    spoj 1812 lcsII (后缀自动机) 题意:求多个串的lcs,最多10个串,每个串最长10w 解题思路:后缀自动机.先建好第一个串的sam,然后后面的串拿上去跑(这个过程同前一题).sam上 ...

随机推荐

  1. 拒绝枯燥,有意思的 Loading 页面动效设计

    互联网时代,网络“提速”日益频繁,人们打开Web或软件的速度越来越快,一般页面缓冲和加载地过程也是几不可查.然而,在某些情况下,例如软件急需加载大量页面,首页急需加载大量内容,用户下载文件过大,甚至是 ...

  2. 判断字符串是否为回文 python

    回文正序和逆序一样的字符串,例如abccba 方法一 def is_palindrome1(text): l = list(text) l.reverse() t1 = ''.join(l) if t ...

  3. JSP中的一个树型结构

    看方力勋的javaWeb,采用左右值来表示树型结构(就是俺门的多级分类)表结构 页面代码 <%@ page language="java" import="java ...

  4. linux相关文章链接

    薄荷开元网 http://www.mintos.org/

  5. Restful风格wcf调用2——增删改查

    写在前面 上篇文章介绍如何将wcf项目,修改成restful风格的接口,并在上面提供了查询的功能,上篇文章中也感谢园友在评论中的提的建议,自己也思考了下,确实是那个道理.在urltemplate中,定 ...

  6. Shell编程-03-Shell中的特殊变量和扩展变量

    目录 特殊变量 变量扩展 特殊变量     在Shell中的特殊变量主要分别两种位置参数变量.状态变量两种. 位置参数变量     Shell中的位置参数变量主要是指$0.$1.$#等,主要用于从命令 ...

  7. cocos2dx常见场景切换动画(转)

    本文转载自:http://www.cnblogs.com/linux-ios/archive/2013/04/09/3010779.html bool HelloWorld::init() { /// ...

  8. linux查看占用内存多的进程

    update一个简单的方法 ps aux | sort -k4nr | head -10 ps -e  -o "%C  : %p : %z : %a"|sort -k5 -nr|h ...

  9. jQuery-关于Ajax请求async属性的说明及总结

    在jquery的ajax中如果希望实现同步或者异步,我们可以设置async(默认true,表示异步请求),下面举例说明两种请求方式的区别. 1.后台代码 public JsonResult GetDa ...

  10. Java中的内部类(二)成员内部类

    Java中的成员内部类(实例内部类):相当于类中的一个成员变量,下面通过一个例子来观察成员内部类的特点 public class Outer { //定义一个实例变量和一个静态变量 private i ...