后缀自动机感觉好万能

tries图和ac自动机能做的,后缀自动机很多也都可以做

这里的循环匹配则是后缀自动机能做的另一个神奇功能

循环匹配意思就是S是abba, T是abb

问'abb', 'bba','bab'在S中出现过多少次。

我们先把T的末尾循环加一遍,变成abbab

然后把问题转换成,求T的每个后缀和S的最长公共子串

如果最长公共子串的长度大于等于T的长度,那么就说明这个后缀匹配成功

做法就是先对S建立一个后缀自动机,然后记录一个状态

(u, l),u表示当前在后缀自动机匹配的位置,l表示最长公共子串的长度

考虑转移的话,就是

如果下一个位置可以匹配,那么u就到相应的位置,l = l+1

答案更新的时候要注意,如果l大于T的长度len,就需要顺着link往前走到第一个能匹配的位置,即第一个maxlen[x] >= len的地方,然后答案加上endpos[x],不然会丢一部分答案。

如果下一个位置不可以匹配,那么u就顺着link边走,走到第一个能匹配的地方,如果找不到,那u就设成起点,l为0

还有一个问题就是串重复的情况,比如说T是aa,那么扩充就会变成aaa,aa和aa重复。

如果串重复的话,那么必定会到同一个状态,所以一个状态标记一下,只更新一遍答案就可以了

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
using namespace std;
int n = , len, st;
const int maxL = 1e6 + ;
int maxlen[*maxL], minlen[*maxL], trans[*maxL][], slink[*maxL], lab[*maxL], son[*maxL], endpos[*maxL];
map<int, bool> vis;
int new_state(int _maxlen, int _minlen, int *_trans, int _slink){
maxlen[n] = _maxlen;
minlen[n] = _minlen;
for(int i = ; i < ; i++){
if(_trans == NULL)
trans[n][i] = -;
else
trans[n][i] = _trans[i];
}
slink[n] = _slink;
return n++;
} int add_char(char ch, int u){
int c = ch - 'a';
int z = new_state(maxlen[u]+, -, NULL, -); lab[z] = ;
int v = u;
while(v != - && trans[v][c] == -){
trans[v][c] = z;
v = slink[v];
}
if(v == -){
minlen[z] = ;
slink[z] = ;
return z;
}
int x = trans[v][c];
if(maxlen[v] + == maxlen[x]){
minlen[z] = maxlen[x] + ;
slink[z] = x;
return z;
}
int y = new_state(maxlen[v] + , -, trans[x], slink[x]);
slink[y] = slink[x];
minlen[x] = maxlen[y] + ;
slink[x] = y;
minlen[z] = maxlen[y] + ;
slink[z] = y;
int w = v;
while(w != - && trans[w][c] == x){
trans[w][c] = y;
w = slink[w];
}
minlen[y] = maxlen[slink[y]] + ;
return z;
} char str[maxL];
int main()
{
cin>>str;
st = new_state(, , NULL, -);
int len = strlen(str);
for(int i = ; i < len; i++) {
st = add_char(str[i], st);
}
for(int i = ; i <= n; i++) son[slink[i]]++;
queue<int> Q;
for(int i = ; i <= n; i++) if(son[i] == ) Q.push(i), endpos[i] = ;
while(!Q.empty()){
int x = Q.front(); Q.pop();
if(x == ) continue;
int y = slink[x];
son[y]--; endpos[y] += endpos[x];
if(son[y] == ){
if(lab[y]) endpos[y]++;
Q.push(y);
}
}
int T;
cin>>T;
while(T--){
vis.clear();
cin>>str;
int len = strlen(str), ylen = len;
for(int i = len; i < *len-; i++) str[i] = str[i-len];
len = *len-;
int u = , l = , ans = ;
for(int i = ; i < len; i++){
int c = str[i] - 'a';
if(trans[u][c] != -){
u = trans[u][c];
l++;
} else {
int y = slink[u];
while(y != -){
if(trans[y][c] != -){
l = maxlen[y] + ;
u = trans[y][c];
break;
}
u = y;
y = slink[u];
}
if(y == -) { u = ; l = ; }
}
if(l >= ylen){
int y = slink[u];
while(maxlen[y] >= ylen) { u = y; y = slink[u]; l = maxlen[u]; }
if(vis[u]) continue;
vis[u] = ;
ans += endpos[u];
}
}
cout<<ans<<endl;
}
return ;
}

hihocoder 1465 循环串匹配问题(后缀自动机)的更多相关文章

  1. hiho# 1465 重复旋律8 循环串计数 后缀自动机

    题目传送门 题意:给出一个母串,再给出n个串,问对于每个串,母串中有几个子串是可以通过循环变化得到这个串. 思路:对母串建SAM,求出$right$集. 把匹配串复制一遍,和母串进行匹配,当匹配长度大 ...

  2. hihoCoder #1465 : 后缀自动机五·重复旋律8

    http://hihocoder.com/problemset/problem/1465 求S的循环同构串在T中的出现次数 将串S变成SS 枚举SS的每个位置i,求出以i结尾的SS的子串 与 T的最长 ...

  3. hihocoder 后缀自动机五·重复旋律8 求循环同构串出现的次数

    描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 小Hi发现旋律可以循环,每次把一段旋律里面最前面一个音换到最后面就成为了原旋律的“循环相似旋律”,还可以 ...

  4. 后缀自动机专题(hihocoder)

    传送门 #1445 : 后缀自动机二·重复旋律5 题意: 给出字符串\(s\),询问字符串\(s\)中有多少不同的子串. 思路: 考虑对\(s\)建后缀自动机,那么\(\sum (len[i]-len ...

  5. 【hihocoder#1413】Rikka with String 后缀自动机 + 差分

    搞了一上午+接近一下午这个题,然后被屠了个稀烂,默默仰慕一晚上学会SAM的以及半天4道SAM的hxy大爷. 题目链接:http://hihocoder.com/problemset/problem/1 ...

  6. hihoCoder 后缀自动机三·重复旋律6

    后缀自动机三·重复旋律6 时间限制:15000ms 单点时限:3000ms 内存限制:512MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一个音乐旋律被表示为一段数构成的数列. 现在小Hi ...

  7. 【hihoCoder 1466】后缀自动机六·重复旋律9

    http://hihocoder.com/problemset/problem/1466 建出A串和B串的两个后缀自动机 对后缀自动机的每个状态求出sg值. 求出B串的\(sum(x)\),表示B有多 ...

  8. hihocoder 后缀自动机专题

    一.后缀自动机基本概念的理解 1.首先后缀自动机的状态是由子串的endpos来决定的 子串的endpos是指一个子串可以在原字符串的哪些位置进行匹配, endpos构成的不同集合划分成不同的状态 关于 ...

  9. hiho一下第131周 后缀自动机二·重复旋律8(循环相似子串)

    后缀自动机五·重复旋律8 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi平时的一大兴趣爱好就是演奏钢琴.我们知道一段音乐旋律可以被表示为一段数构成的数列. 小Hi ...

随机推荐

  1. Linux系统修改/etc/sysconfig/i18n文件,桌面无法正常显示

    在Windows环境下使用SSH Secure Shell Client登陆VMware Workstation中Linux系统查询hive表时,中文显示乱码:数字和url显示为NULL,网上说: 1 ...

  2. CVE-2017-11882复现-office命令执行

    0x01 前言 11月14日,微软按照惯例发布了11月的安全更新,随后不久,安全公司EMBEDI在官方博客上公开了其向微软提交的编号为CVE-2017-11882的Office远程代码执行漏洞: ht ...

  3. 图片懒加载 jquery.lazyload

    <!doctype html> <html> <head> <meta charset="utf-8"> <title> ...

  4. 浅谈C#实现Web代理服务器的几大步骤

    代理服务程序是一种广泛使用的网络应用程序.代理程序的种类非常多,根据协议不同可以分成HTTP代理服务程序.FTP代理服务程序等,而运行代理服务程序的服务器也就相应称为HTTP代理服务器和FTP代理服务 ...

  5. 查询表名里含有Bill的表有哪些

    Select Name from Master.dbo.sysobjects where xtype='u' and Name like '%Bill%' order by name

  6. u-boot、kernel、root系统烧写和挂载命令命令

    一.uboot 环境变量: 1. 打印环境变量:# print 2. 设置启动参数# set bootargs noinitrd init=/linuxrc console=ttySAC0,11520 ...

  7. 最小生成树算法 1.Prim算法

    最小生成树(MST):一个有N个点的图,边一定是大于等于N-1条边的.在这些边中选择N-1条出来,连接所有N个点.这N-1条边的边权之和是所有方案中最小的. Prim算法的时间复杂度时O(n^2)的, ...

  8. HBase Scan,Get用法

    Scan,get用法 1. get help帮助信息 从下列get用法信息可以看出 get 后面可以跟table表名,rowkey,以及column,value.但是如果想通过get直接获取一个表中的 ...

  9. elasticsearch 关联查询

    父-子关系文档 父-子关系文档 在实质上类似于 nested model :允许将一个对象实体和另外一个对象实体关联起来. 而这两种类型的主要区别是:在 nested objects 文档中,所有对象 ...

  10. netty源码分析系列文章

    netty源码分析系列文章 nettynetty源码阅读netty源码分析  想在年终之际将对netty研究的笔记记录下来,先看netty3,然后有时间了再写netty4的,希望对大家有所帮助,这个是 ...