A substring of a string T is defined as:

                Tik)= TiTi +1... Ti+k -1, 1≤ i≤ i+k-1≤| T|.

Given two strings AB and one integer K, we define S, a set of triples (ijk):

S = {( ijk) | k≥ KAik)= Bjk)}.

You are to give the value of |S| for specific AB and K.

Input

The input file contains several blocks of data. For each block, the first line contains one integer K, followed by two lines containing strings A and B, respectively. The input file is ended by K=0.

1 ≤ |A|, |B| ≤ 105
1 ≤ K ≤ min{|A|, |B|}
Characters of A and B are all Latin letters.

Output

For each case, output an integer |S|.

Sample Input

2
aababaa
abaabaa
1
xx
xx
0

Sample Output

22
5

题意:

找出S,T两串中所有相同的长度大于等于K的字符串。不判重,即位置不同的相同串要重复统计。

解法:

  • 已知,对于一个串S,后缀自动机可以得到其所有的子串,以及递推出不同字串出现的数量num。
  • 对于匹配串T,一个字符一个字符的走一趟自动机(假设现在走到了T[i]),可以得到S中以T[i]结尾的集合,然后用集合中满足>=k的元素乘以num。
  • 里面有拓扑关系,用了lazy标记。
  • 加了输入优化,时间排名第三。

注意:

ans=ans+(long long)lazy[p]*(maxlen[p]-max(K,maxlen[slink[p]]+)+)*num[p];

开始把long long的位置写错了,wa了很多次。

错误位置:ans=(long long)ans+lazy[p]*(maxlen[p]-max(K,maxlen[slink[p]]+)+)*num[p];

(难道是先执行乘法,这个时候long long无效?)

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<memory>
#include<algorithm>
using namespace std;
const int maxn=;
int K;char chr[maxn];
struct SAM
{
int sz,Last,ch[maxn][],slink[maxn],maxlen[maxn];
int c[maxn],pos[maxn],num[maxn],lazy[maxn];
//num表示一个模板串S中x集合出现的次数,lazy表示匹配串T中x集合的累加(向上slink(fa)传递)。
//pos是拓扑排序后的结果,用来递推num和lazy。
long long ans;
int get(char x)
{
if(x>='a'&&x<='z') return x-'a';
return x-'A'+;
}
void init()
{
sz=; Last=sz=;
memset(ch[],,sizeof(ch[]));
num[]=lazy[]=;
}
void add(int x)
{
int np=++sz,p=Last;Last=np;
lazy[sz]=;num[sz]=;
maxlen[np]=maxlen[p]+;
memset(ch[np],,sizeof(ch[np]));
while(p&&!ch[p][x]) ch[p][x]=np,p=slink[p];
if(!p) slink[np]=;
else {
int q=ch[p][x];
if(maxlen[q]==maxlen[p]+) slink[np]=q;
else {
int nq=++sz; lazy[sz]=num[sz]=;
memcpy(ch[nq],ch[q],sizeof(ch[q]));
slink[nq]=slink[q],slink[np]=slink[q]=nq;
maxlen[nq]=maxlen[p]+;
while(p&&ch[p][x]==q) ch[p][x]=nq,p=slink[p];
}
}
}
void sort()
{
for(int i=;i<=sz;i++) c[i]=;
for(int i=;i<=sz;i++) c[maxlen[i]]++;
for(int i=;i<=sz;i++) c[i]+=c[i-];
for(int i=;i<=sz;i++) pos[c[maxlen[i]]--]=i;
for(int i=sz;i>=;i--) num[slink[pos[i]]]+=num[pos[i]];
}
void solve()
{
char c=getchar();
while(!(c>='a'&&c<='z')&&!(c>='A'&&c<='Z')) c=getchar();
int mp=,Len=;ans=;
while((c>='a'&&c<='z')||(c>='A'&&c<='Z')) {
int x=get(c);c=getchar();
if(ch[mp][x]){ Len++; mp=ch[mp][x];}
else {
while(mp&&!ch[mp][x]) mp=slink[mp];
if(!mp) { mp=; Len=; }//~
else { Len=maxlen[mp]+; mp=ch[mp][x]; }
}
if(Len>=K) {
ans=(long long)ans+(Len-max(maxlen[slink[mp]]+,K)+)*num[mp];
if(maxlen[slink[mp]]>=K) lazy[slink[mp]]++;
}
}
for(int i=sz;i>=;i--) {
int p=pos[i];
ans=ans+(long long)lazy[p]*(maxlen[p]-max(K,maxlen[slink[p]]+)+)*num[p];
if(maxlen[slink[p]]>=K) lazy[slink[p]]+=lazy[p];
}
printf("%lld\n",ans);
}
};
SAM sam;
int main()
{
while(~scanf("%d",&K)){
if(K==) return ;
sam.init();
char c=getchar();
while(!(c>='a'&&c<='z')&&!(c>='A'&&c<='Z')) c=getchar();
while((c>='a'&&c<='z')||(c>='A'&&c<='Z')) sam.add(sam.get(c)),c=getchar();
sam.sort();
sam.solve();
}
return ;
}

POJ3415Common Substrings(后缀自动机)的更多相关文章

  1. 【CF316G3】Good Substrings 后缀自动机

    [CF316G3]Good Substrings 题意:给出n个限制(p,l,r),我们称一个字符串满足一个限制当且仅当这个字符串在p中的出现次数在[l,r]之间.现在想问你S的所有本质不同的子串中, ...

  2. SPOJ NSUBSTR Substrings 后缀自动机

    人生第一道后缀自动机,总是值得纪念的嘛.. 后缀自动机学了很久很久,先是看CJL的论文,看懂了很多概念,关于right集,关于pre,关于自动机的术语,关于为什么它是线性的结点,线性的连边.许多铺垫的 ...

  3. ●SPOJ 8222 NSUBSTR–Substrings(后缀自动机)

    题链: http://www.spoj.com/problems/NSUBSTR/ 题解: 后缀自动机的水好深啊!懂不了相关证明,带着结论把这个题做了.看来这滩深水要以后再来了. 本题要用到一个叫 R ...

  4. SPOJ8222 NSUBSTR - Substrings(后缀自动机)

    You are given a string S which consists of 250000 lowercase latin letters at most. We define F(x) as ...

  5. SPOJ NSUBSTR Substrings ——后缀自动机

    建后缀自动机 然后统计次数,只需要算出right集合的大小即可, 然后更新f[l[i]]和rit[i]取个max 然后根据rit集合短的一定包含长的的性质,从后往前更新一遍即可 #include &l ...

  6. spoj 8222 Substrings (后缀自动机)

    spoj 8222 Substrings 题意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.求F(1)..F(Length(S)) 解题思路:我们构造S的SAM,那么对于 ...

  7. UVA - 10829 L-Gap Substrings (后缀自动机+线段树启发式合并)

    题意:统计一段字符串中形如UVU的子串个数(其中V的长度固定为g). 问题等价于求满足$g+1\leqslant |j-i|\leqslant g+LCP(i,j)$的后缀(i,j)的对数,即$\su ...

  8. SPOJ8222 Substrings( 后缀自动机 + dp )

    题目大意:给一个字符串S,令F(x)表示S的所有长度为x的子串中,出现次数的最大值.F(1)..F(Length(S)) 建出SAM, 然后求出Right, 求Right可以按拓扑序dp..Right ...

  9. SPOJ8222 NSUBSTR - Substrings 后缀自动机_动态规划

    讲起来不是特别好讲.总之,如果 $dp[i+1]>=dp[i]$,故$dp[i]=max(dp[i],dp[i+1])$ Code: #include <cstdio> #inclu ...

  10. SP8222 NSUBSTR - Substrings(后缀自动机+dp)

    传送门 解题思路 首先建出\(sam\),然后把\(siz\)集合通过拓扑排序算出来.对于每个点只更新它的\(maxlen\),然后再从大到小\(dp\)一次就行了.因为\(f[maxlen-1]&g ...

随机推荐

  1. JavaScript基础入门07

    目录 JavaScript 基础入门07 BOM window对象 Navigator对象 Screen 对象 Location对象 History 对象 JavaScript 基础入门07 BOM ...

  2. JavaScript基础之数组常用方法

    目录 JS 数组常用API 常用属性 常用方法 常见方法语法解释 from方法 isArray concat every fill filter find forEach indexOf join k ...

  3. 【Linux】常用基础命令

    修改时间 date -s 月/日/年 例如:date -s 07/31/2019 date -s 时:分:秒 例如:date -s 23:56:50 hwclock -w 将时间写到bois,防止重启 ...

  4. 【并行计算-CUDA开发】Windows下opencl环境配置

    首先声明我这篇主要是根据下面网站的介绍, 加以修改和详细描述,一步一步在我自己的电脑上实现的, http://www.cmnsoft.com/wordpress/?tag=opencl&pag ...

  5. BP原理 - 前向计算与反向传播实例

    Outline 前向计算 反向传播 很多事情不是需要聪明一点,而是需要耐心一点,踏下心来认真看真的很简单的. 假设有这样一个网络层: 第一层是输入层,包含两个神经元i1 i2和截距b1: 第二层是隐含 ...

  6. linux shadow文件格式弱口令解密

    shadow格式弱口令为linux弱口令,通过kali linux 终端 john --w=字典 加上shadow文件, 扫描完成之后通过john --show 加上shadow文件出结果

  7. 小记---------sparkRDD的Transformation 和 Action 及案例 原理解释

    RDD :弹性分布式数据集:是一个容错的.并行的数据结构,可以让用户显式地将数据存储到磁盘或内存中,并控制数据的分区   RDD是Spark的核心数据结构,通过RDD的依赖关系形成Spark的调度顺序 ...

  8. python基础数据类型和初级应用

    1.整数: int -- 计算和比较 2 -- 10 推位 8421 20 21 -- 2**7 10 - 2 bit_length 二进制的有效占用位数 # 123 # 计算和比较 # 14 0 # ...

  9. js判断设备,跳转app应用、android市场或者AppStore

    js移动设备判断方法大全 <!DOCTYPE html> <html> <head> <meta charset="UTF-8" > ...

  10. PermissionError: [Errno 13] Permission denied: '/run/user/0/jupyter'

    解决办法:需要给/run/user整个目录开放权限,不能单独给'/run/user/0/jupyter'这个文件,因为jupyter是需要往目录中添加文件,/run/user/0/jupyter,此时 ...