后缀数组,看到网上很多题解都是单调栈,这里提供一个不是单调栈的做法,

首先将两个串 连接起来求height   求完之后按height值从大往小合并。  height值代表的是  sa[i]和sa[i-1] 的公共前缀长度,那么每次合并就是合并  i和i-1 那么在合并小的时候公共前缀更大的肯定已经都合并在一起,那么就可以直接统计了。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<time.h>
#include<string>
#define cl(a,b) memset(a,b,sizeof(a))
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define REP(i,n) for(int i=0;i<n;++i)
#define REP1(i,a,b) for(int i=a;i<=b;++i)
#define REP2(i,a,b) for(int i=a;i>=b;--i)
#define MP make_pair
#define LL long long
#define ULL unsigned long long
#define X first
#define Y second
using namespace std; const int MAXN = 200050; struct SuffixArray{
int wa[MAXN];
int wb[MAXN];
int wv[MAXN];
int ws[MAXN]; int sa[MAXN];
int rank[MAXN];
int height[MAXN];
int r[MAXN];
int n;
int m; void input(int *val, int len, int Max){
for (int i = 0;i < len;i++)
r[i] = val[i];
r[len] = 0;
n = len;
m = Max;
calSa();
calHeight();
} int cmp(int *r, int a, int b, int l){
return (r[a] == r[b] && r[a + l] == r[b + l]);
} void calSa(){
int i, j, p, *x = wa, *y = wb, *t;
for (i = 0;i < m;i++) ws[i] = 0;
for (i = 0;i < n + 1;i++) ws[x[i] = r[i]]++;
for (i = 1;i < m;i++) ws[i] += ws[i - 1];
for (i = n;i >= 0;i--) sa[--ws[x[i]]] = i;
for (j = 1, p = 1;p < n + 1;j *= 2, m = p){
for (p = 0, i = n - j + 1;i < n + 1;i++) y[p++] = i;
for (i = 0;i < n + 1;i++) if (sa[i] >= j) y[p++] = sa[i] - j;
for (i = 0;i < n + 1;i++) wv[i] = x[y[i]];
for (i = 0;i < m;i++) ws[i] = 0;
for (i = 0;i < n + 1;i++) ws[wv[i]]++;
for (i = 1;i < m;i++) ws[i] += ws[i - 1];
for (i = n;i >= 0;i--) sa[--ws[wv[i]]] = y[i];
for (t = x, x = y, y = t, p = 1, x[sa[0]] = 0, i = 1; i < n + 1;i++)
x[sa[i]] = cmp(y, sa[i - 1], sa[i], j) ? p - 1 : p++;
}
} void calHeight(){
int i, j, k = 0;
for (i = 1;i <= n;i++) rank[sa[i]] = i;
for (i = 0;i < n;height[rank[i++]] = k)
for (k?k--:0, j = sa[rank[i]- 1];r[i + k] == r[j + k];k++);
} }SA;
char s1[MAXN],s2[MAXN];
int s[MAXN];
vector<int>e[MAXN];
int id[MAXN];
int x[MAXN],y[MAXN];
int fa[MAXN];
int getfa(int x)
{
if(fa[x]==x)return x;
else
return fa[x]=getfa(fa[x]);
}
int main()
{
int k;
while(scanf("%d",&k)&&k)
{
int h=0,len1,len2;
scanf(" %s %s",s1,s2);
len1=strlen(s1);
len2=strlen(s2);
for(int i=0;i<len1;++i)
{
id[h]=0;
s[h++]=s1[i];
}
s[h++]=1;
for(int i=0;i<len2;++i)
{
id[h]=1;
s[h++]=s2[i];
}
SA.input(s,h,500);
// for(int i=0;i<=h;++i)
// printf("%d %d %d\n",i,SA.sa[i],SA.height[i]);
for(int i=0;i<=h;++i)
e[i].clear();
for(int i=1;i<=h;++i)
{
e[SA.height[i]].push_back(i);
}
for(int i=0;i<=h;++i)
{
fa[i]=i;
if(id[SA.sa[i]]==0)//这里要用sa来判断原先属于哪个串
x[i]=1,y[i]=0;
else
x[i]=0,y[i]=1;
}
LL ans=0;
for(int i=h;i>=k;--i)
{
for(int j=0;j<e[i].size();++j)
{
int u=e[i][j];
int f1=getfa(u);
int f2=getfa(u-1);
// printf("%d %d\n",f1,f2);
if(f1!=f2){
ans-=(LL)x[f2]*y[f2]*(i-k+1);//减去原先的贡献值
ans-=(LL)x[f1]*y[f1]*(i-k+1);//减去原先的贡献值
fa[f1]=f2;
x[f2]+=x[f1];
y[f2]+=y[f1];
ans+=(LL)x[f2]*y[f2]*(i-k+1);//加上新的
}
}
}
printf("%I64d\n",ans);
}
}

  

POJ 3415 Common Substrings 后缀数组+并查集的更多相关文章

  1. poj 3415 Common Substrings —— 后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 先用后缀数组处理出 ht[i]: 用单调栈维护当前位置 ht[i] 对之前的 ht[j] 取 min 的结果,也就是当前的后缀与之前 ...

  2. poj 3415 Common Substrings——后缀数组+单调栈

    题目:http://poj.org/problem?id=3415 因为求 LCP 是后缀数组的 ht[ ] 上的一段取 min ,所以考虑算出 ht[ ] 之后枚举每个位置作为右端的贡献. 一开始想 ...

  3. POJ - 3415 Common Substrings (后缀数组)

    A substring of a string T is defined as: T( i, k)= TiTi +1... Ti+k -1, 1≤ i≤ i+k-1≤| T|. Given two s ...

  4. poj 3415 Common Substrings 后缀数组+单调栈

    题目链接 题意:求解两个字符串长度 大于等于k的所有相同子串对有多少个,子串可以相同,只要位置不同即可:两个字符串的长度不超过1e5; 如 s1 = "xx" 和 s2 = &qu ...

  5. poj 3415 Common Substrings - 后缀数组 - 二分答案 - 单调栈

    题目传送门 传送点I 传送点II 题目大意 给定串$A, B$,求$A$和$B$长度大于等于$k$的公共子串的数量. 根据常用套路,用一个奇怪的字符把$A$,$B$连接起来,然后二分答案,然后按mid ...

  6. POJ - 3415 Common Substrings(后缀数组求长度不小于 k 的公共子串的个数+单调栈优化)

    Description A substring of a string T is defined as: T( i, k)= TiTi+1... Ti+k-1, 1≤ i≤ i+k-1≤| T|. G ...

  7. POJ 3415 Common Substrings ——后缀数组

    [题目分析] 判断有多少个长度不小于k的相同子串的数目. N^2显然是可以做到的. 其实可以维护一个关于height的单调栈,统计一下贡献,就可以了. 其实还是挺难写的OTZ. [代码] #inclu ...

  8. POJ.3145.Common Substrings(后缀数组 倍增 单调栈)

    题目链接 \(Description\) 求两个字符串长度不小于k的公共子串对数. \(Solution\) 求出ht[]后先减去k,这样对于两个后缀A',B',它们之间的贡献为min{ht(A)}( ...

  9. POJ 3415 Common Substrings(后缀数组 + 单调栈)题解

    题意: 给两个串\(A.B\),问你长度\(>=k\)的有几对公共子串 思路: 先想一个朴素算法: 把\(B\)接在\(A\)后面,然后去跑后缀数组,得到\(height\)数组,那么直接\(r ...

随机推荐

  1. Mac下遇到 'reading initial communication packet’ 问题

    今天在开发过程中,一个单位跑的好好的项目,在家中的Mac下运行时,遇到了下面这个错误:   "Lost connection to MySQL server at 'reading init ...

  2. SQL-Server使用点滴(一)

    前言 SQL的语法比较简单,学起来相比界面UI控制要简单得多,但是SQL在企业级应用中又是如此的重要,以至于很多开发人员都把重点放在SQL上. SQL并没有面向对象的概念,最复杂的设计也不过是表值函数 ...

  3. Linux下不同服务器间数据传输--转载

    因为工作原因,需要经常在不同的服务器见进行文件传输,特别是大文件的传输,因此对linux下不同服务器间数据传输命令和工具进行了研究和总结.主要是rcp,scp,rsync,ftp,sftp,lftp, ...

  4. XAF视频教程来啦,已出15课

    第一到第七课在这里: http://www.cnblogs.com/foreachlife/p/xafvideo_1_6.html 视频地址:http://i.youku.com/i/UMTI5OTE ...

  5. html4,xhtml,html5发展历史

    SGML SGML 是一种很强大但很复杂的标记语言,HTML.XML 就是从中衍生出来的.SGML 的例子如下:<QUOTE TYPE="example"> typic ...

  6. Mac安装ctags

    Mac安装ctags mac 系统有自带的ctags,但是不支持"ctags -R"指令,需要自己在安装Exuberant Ctags 1.下载ctags 2. 安装 ./conf ...

  7. cookie记录用户名

    在说如何用cookie记录用户名之前,我们先来说说cookie的工作原理: cookie : 存储数据,当用户访问了某个网站(网页)的时候,我们就可以通过cookie来像访问者电脑上存储数据 ; 1. ...

  8. 浅谈 原生javaScript&&react 实现全局触摸按钮(附带对addeventlistener的了解)

    1.采用原生javaACript 实现全局触摸按钮 首先在控制台输出,观察事件有哪些关于触摸的字段可以使用,然后拿这些字段的数据开始来写方法. 因为要做的是全局触摸按钮,我需要拿到的是按钮时时的坐标位 ...

  9. java中的数据结构(集合|容器)

    对java中的数据结构做一个小小的个人总结,虽然还没有到研究透彻jdk源码的地步.首先.java中为何需要集合的出现?什么需求导致.我想对于面向对象来说,对象适用于描述任何事物,所以为了方便对于对象的 ...

  10. 报错记录:getOutputStream() has already been called for this response

    仅作记录:参考文章:http://www.blogjava.net/vickzhu/archive/2008/11/03/238337.html 报错信息: java.lang.IllegalStat ...