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. 解决win10 windows mobile 设备中心无法打开问题,MC3200无法连上win10问题

    1.下载高版本的安装包 从微软官方下载:https://www.microsoft.com/zh-cn/download/confirmation.aspx?id=3182 2.  运行service ...

  2. docker遇到防火墙报错问题解决方法

    -- 报错信息[root@localhost docker]# docker run -d -p 5000:5000 training/webapp python app.pycc61442060cb ...

  3. 学习ansible笔记1

    ansible的特点: -- 模块化设计 -- 仅需要ssh和Python即可以使用 -- 无客户端 -- 功能强大,模块丰富 -- 上手容易门槛低 -- 基于python开发,做二次开发更容易 -- ...

  4. CISCO路由器WAN口动态ISP配置

        Building configuration... version 15.0 service timestamps debug datetime msec service timestamps ...

  5. Centos 安装k8s 集群(单master开发环境)

    本教程是在VM中搭建K8s 所以第一步骤先配置虚拟机的ip 和上网情况详细参考https://www.cnblogs.com/chongyao/p/9209527.html 开始搭建K8s集群 两台机 ...

  6. nginx集群+mysql数据同步

    mysql集群配置在网站负载均衡中是必不可少的: 首先说下我个人准备的负载均衡方式: 1.通过nginx方向代理来将服务器压力分散到各个服务器上: 2.每个服务器中代码逻辑一样: 3.通过使用redi ...

  7. JCC指令

    0.JMP1.JE, JZ 结果为零则跳转(相等时跳转) ZF=12.JNE, JNZ 结果不为零则跳转(不相等时跳转) ZF=03.JS   结果为负则跳转   SF=14.JNS   结果为非负则 ...

  8. 2016年蓝桥杯省赛C++A组 消除尾一

    消除尾一: 下面的代码把一个整数的二进制表示的最右边的连续的1全部变成0如果最后一位是0,则原数字保持不变. 如果采用代码中的测试数据,应该输出: 00000000000000000000000001 ...

  9. tp5.1中redis使用

    一.环境安装 1.下载redis,igbniary https://windows.php.net/downloads/pecl/releases/igbinary/ https://windows. ...

  10. Linux系统定时备份网站文件到七牛云存储脚本

    1.七牛云账号注册. 有些朋友可能会问为什么要备份到七牛云?很简单,七牛云免费注册就能获取1G的存储空间,只要简单几步操作完成实名认证即可获取10G的存储空间,对于一般个人站点来说已经足够备份使用了. ...