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. 如何在google colab加载kaggle数据

    参考https://medium.com/@yvettewu.dw/tutorial-kaggle-api-google-colaboratory-1a054a382de0 从本地上传到colab上十 ...

  2. Partition to K Equal Sum Subsets

    Given an array of integers nums and a positive integer k, find whether it's possible to divide this ...

  3. 大型软件公司.Net面试常见题(含答案)

    1.a=10,b=15,在不用第三方变量的前提下,吧a.b互换 2.已知数组int[] max={6,5,2,9,7,4,0};用快速排序算法按降序对其进行排列,并返回数组 3.请简述面向对象的多态的 ...

  4. 在Ubuntu上安装Hive

    1.下载hive2.3.5 解压缩并改名为hive目录,放到/usr/local下(注意权限) sudo mv apache-hive-2.3.5-bin /usr/local/hive 2.修改目录 ...

  5. Struts 2访问Servlet API

    在servlet中可以通过servlet API来获取Session,在Struts中如何获取Session呢? 解析:将用户名放入session 两种方案 1. 与Servlet API解耦的访问方 ...

  6. 什么是云数据库RDS PostgreSQL 版

    PostgreSQL被业界誉为“最先进的开源数据库”,面向企业复杂SQL处理的OLTP在线事务处理场景,支持NoSQL数据类型(JSON/XML/hstore).支持GIS地理信息处理. 优点 NoS ...

  7. java-selenium浏览器常用操作命令

    一.浏览器操作命令 启动火狐浏览器(49版本以下) System.setProperty("webdriver.firefox.bin","D:\\Firefox\\fi ...

  8. Spring 最常用的 7 大类注解,史上最强整理!

    随着技术的更新迭代,Java5.0开始支持注解.而作为java中的领军框架spring,自从更新了2.5版本之后也开始慢慢舍弃xml配置,更多使用注解来控制spring框架. 而spring的的注解那 ...

  9. 从入门到自闭之Python三大器--生成器

    1.什么是生成器 核心:生成器的本质就是一个迭代器 迭代器是python自带的的 生成器是程序员自己写的一种迭代器 编写方式: 基于函数编写 推导式编写 def func (): print(&quo ...

  10. Java工具类-基于SnowFlake的短地址生成器

    Twitter的SnowFlake算法,使用SnowFlake算法生成一个整数,然后转化为62进制变成一个短地址URL /** * Twitter的SnowFlake算法,使用SnowFlake算法生 ...