P5546 [POI2000]公共串

所有串合在一起,每两个串放不同的字符,求一遍后缀数组,然后利用height数组求LCS即可。

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>using namespace std;const int N = 1e5 + 10;
//sa是排名i的编号,rk是i排名几
int sa[N],rk[N],height[N],cnt[N],oldrk[N],id[N];
string s = "1",b;
int n;
int st[N][20];
void build_sa(){n = s.length();--n;for(int i = 1; i <= n; i++){rk[i] = s[i];++cnt[rk[i]];}int m = 127,p;for(int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];for(int i = n; i >= 1; i--) sa[cnt[rk[i]]--] = i;memcpy(oldrk,rk,sizeof rk);int i;for(p = 0,i = 1; i <= n; i++){if(oldrk[sa[i]] == oldrk[sa[i - 1]]){rk[sa[i]] = p;}else{rk[sa[i]] = ++p;}}int w;for(w = 1; w < n; w <<= 1,m = n){for(int j = 0; j <= n; j++) cnt[j] = 0;memcpy(id,sa,sizeof sa);for(int i = 1; i <= n; i++) ++cnt[rk[id[i] + w]];for(int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];for(int i = n; i >= 1; i--) sa[cnt[rk[id[i] + w]]--] = id[i];for(int j = 0; j <= n; j++) cnt[j] = 0;memcpy(id,sa,sizeof sa);for(int i = 1; i <= n; i++) ++cnt[rk[id[i]]];for(int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];for(int i = n; i >= 1; i--) sa[cnt[rk[id[i]]]--] = id[i];memcpy(oldrk,rk,sizeof rk);for(int p = 0,i = 1; i <= n; i++){if(oldrk[sa[i]] == oldrk[sa[i - 1]]&& oldrk[sa[i] + w] == oldrk[sa[i - 1] + w]){rk[sa[i]] = p;}else{rk[sa[i]] = ++p;}}}for(int i = 1,k = 0; i <= n; i++){if(rk[i] == 0) continue;if(k) --k;while(s[i + k] == s[sa[rk[i] - 1] + k]) ++k;height[rk[i]] = k;}
}void build_st(){for(int i = 1; i <= n; i++) st[i][0] = height[i];for(int j = 1; j <= 19; j++)for(int i = 1; i <= n && i + (1 << j - 1) <= n; i++){st[i][j] = min(st[i][j - 1],st[i + (1 << j - 1)][j - 1]);}
}int query2(int l,int r){int d = log2(r - l + 1);return min(st[l][d],st[r - (1 << d) + 1][d]);
}int max(int x,int y){if(x > y) return x;return y;
}int C[10];int main(){int m;cin >> m;for(int i = 1; i <= m; i++){cin >> b;s += b;s += char('A' + i - 1);C[i] = C[i - 1] + b.length() + 1;}if(m == 1){cout << s.length() - 1 << endl;return 0;}build_sa();build_st();memset(id,0,sizeof id);for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){if(sa[i] < C[j]){id[i] = j;break;}}}//for(int i = 1; i <= n; i++) cout << height[i] << endl;int maxn2 = 0;int flag[10];for(int i = 1; i <= n; i++){int cnt = 0;memset(flag,0,sizeof flag);for(int j = i; j <= n; j++){flag[id[j]]++;if(id[j] != 0 && flag[id[j]] == 1) cnt++;if(cnt == m){maxn2 = max(maxn2,query2(i + 1,j));//cout << i << " " << j << " " << maxn2 << endl;break;}}}cout << maxn2 << endl;return 0;
}

SP1811 LCS - Longest Common Substring

如上做法
LCS2 - Longest Common Substring II

放弃st表,使用单调队列优化即可。

#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>using namespace std;const int N = 2e6 + 10;
//sa是排名i的编号,rk是i排名几
int sa[N],rk[N],height[N],cnt[N],oldrk[N],id[N],key1[N];
string s = "1",b;
int n;
int st[N][22];
void build_sa(){n = s.length();--n;memset(rk,0,sizeof rk);memset(cnt,0,sizeof cnt);memset(sa,0,sizeof sa);for(int i = 1; i <= n; i++){rk[i] = s[i];++cnt[rk[i]];}int m = 127,p,i;for(int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];for(int i = n; i >= 1; i--) sa[cnt[rk[i]]--] = i;int w;for(w = 1;; w <<= 1,m = p){for(p = 0,i = n; i > n - w; --i) id[++p] = i;for(int i = 1; i <= n; i++) if(sa[i] > w) id[++p] = sa[i] - w;memset(cnt,0,sizeof cnt);for(int i = 1; i <= n; i++) ++cnt[key1[i] = rk[id[i]]];for(int i = 1; i <= m; i++) cnt[i] += cnt[i - 1];for(int i = n; i >= 1; i--) sa[cnt[key1[i]]--] = id[i];memcpy(oldrk,rk,sizeof rk);for(p = 0,i = 1; i <= n; i++){if(oldrk[sa[i]] == oldrk[sa[i - 1]]&& oldrk[sa[i] + w] == oldrk[sa[i - 1] + w]){rk[sa[i]] = p;}else{rk[sa[i]] = ++p;}}if(p == n){for(int i = 1; i <= n; i++) sa[rk[i]] = i;break;}}for(int i = 1,k = 0; i <= n; i++){if(rk[i] == 0) continue;if(k) --k;while(s[i + k] == s[sa[rk[i] - 1] + k]) ++k;height[rk[i]] = k;}}int max(int x,int y){if(x > y) return x;return y;
}int C[12];int main(){ios::sync_with_stdio(false);int m = 0;s = "1";while(cin >> b){++m;s += b;s += char('A' + m - 1);C[m] = C[m - 1] + b.length() + 1;}if(m == 1){cout << s.length() - 2 << endl;return 0;}build_sa();memset(id,0,sizeof id);for(int i = m + 1; i <= n; i++){for(int j = 1; j <= m; j++){if(sa[i] < C[j]){id[i] = j;break;}}}//for(int i = 1; i <= n; i++) cout << height[i] << endl;int maxn2 = 0;int flag[20] = {};int k = m + 1;int cnt = 0;static int q[N];int st = 1,ed = 0;for(int i = m + 1; i <= n; i++){while(q[st] <= i && st <= ed) st++;if(cnt == m){maxn2 = max(maxn2,height[q[st]]);flag[id[i]]--;if(id[i] != 0 && flag[id[i]] == 0) cnt--;continue;}for(int j = k; j <= n; j++){flag[id[j]]++;while(height[j] <= height[q[ed]] && ed >= st) ed--;q[++ed] = j;if(id[j] != 0 && flag[id[j]] == 1) cnt++;if(cnt == m){maxn2 = max(maxn2,height[q[st]]);   k = j + 1;break;}k = j + 1;}flag[id[i]]--;if(id[i] != 0 && flag[id[i]] == 0) cnt--;}cout << maxn2 << endl;return 0;
}

SP10570 LONGCS - Longest Common Substring
如上做法

sa后缀数组使用合集,包括height数组求LPC和LCS,ST表,单调队列优化。相关推荐

  1. PHP 数组方法合集

    创建数组 1.array()  创建一个新数组 2.array_combine($a,$b)  创建一个新数组,用$a的值 作为键,用$b的值作为value值,如果2个数组长度不同则返回false; ...

  2. 统计 表格_电商运营表格合集,运营统计绩效策划,全套excel表拿来就用

    Hello大家好,我是帮帮.今天跟大家分享一组电商运营表格合集,运营统计绩效策划,全套excel表格拿来就用. 为了让大家能更稳定的下载模板,我们又开通了全新下载方式(见文章末尾),以便大家可以轻松获 ...

  3. LeetCode(合集)删除数组中的元素(26,80,283)

    26. 删除排序数组中的重复项 80. 删除排序数组中的重复项 II golang 283. 移动零 golang

  4. MySql链接字符串 各种程序连接大合集(包括asp.net,c#,等等)

    一.MySQL Connector/ODBC 2.50 (MyODBC 2.50)连接方式 1.本地数据库连接Driver={MySQL};Server=localhost;Option=16834; ...

  5. php三维数组转换二维数组,php 三维数组转二维数组(多维数组变合拼二维数组)(foreach循环 数组叠加)...

    /*************** * @function 三维数组转二维数组 * @Param: $array : 传入参数 * @Return: $tempArr 返回结果数组 ********** ...

  6. 三角函数公式合集——从诱导公式到求导公式

    1 三角函数间的关系 倒数 商 平方 2 诱导公式 诱导公式口诀:奇边偶不变,符号看象限. 3 倍角三角函数公式 由上面的cos(2 alpha)可推导出如下有用的降幂公式: 4 两角和差公式 5 万 ...

  7. 大合集_用Python求导数

    在我们深度学习神经网络里的反向传播其实就是对损失函数求导.笔者就求导在python中的几种方式进行汇总 一.Scipy求导 由于scipy 是基于numpy写的高级封装, 所以在numpy的生态可以共 ...

  8. 【软件开发合集】各种类型软件开发合集(包括JS,Python和Android)

    [软件开发合集]各种类型软件开发笔记合集,包括JS,Python和Android 1.[基于JS的软件开发笔记] 1.1 基于JavaScript开发的校园综合类微信小程序 2.[基于Python的软 ...

  9. HDU 6194 string string string :后缀数组+单调队列 | 后缀自动机

    题意:给出一个字符串,求出出现了恰好k次的子串的个数. 题解:恰好k次 = 至少k次 - 至少k+1次.答案转化为求至少出现k次的子串个数统计.构造好后缀数组以及很重要的Height数组之后.用一个k ...

最新文章

  1. 论文笔记:PPFNet
  2. 上海:加快推进18个新建数据中心项目的建设和投资进度
  3. idea实现抽象类的所有抽象方法_深入理解Java的接口和抽象类
  4. 高科技的计算机作文,高科技的作文范文400字
  5. linux命令管理GPT分区,Linux磁盘管理GPT分区教程
  6. ant build里如何指定classpath
  7. Structure from motion 问题
  8. ubuntu之间传文件
  9. 正在等待缓存锁:无法获得锁_一句话说清分布式锁,进程锁,线程锁
  10. C# ComboBox自动完成功能的例子
  11. CSS:实现文本超出显示省略效果(可指定几行显示)
  12. 可解释ai_人工智能解释
  13. python 通过逗号分割字符串_「Python 秘籍」使用多个界定符分割字符串
  14. debian nginx php配置文件,在debian上安装配置nginx + php-FPM + APC
  15. QT QDir(获取当前路径下的所有文件)
  16. PCL:三维点云概述(一)
  17. 在linux终端绘图,Boxes - 在Linux终端中绘制ASCII艺术盒子和图形
  18. 【大数据】一图了解大数据发展历程
  19. excel高级筛选怎么用_Excel工作表中如何使用高级筛功能来实现多条件筛选
  20. Android集成腾讯Bugly和简单使用

热门文章

  1. php保留两位小数,四舍五入和有小数就进1(可保留两位小数)
  2. JS如何获取cookie的值
  3. 用python画小仓鼠教程_彩铅动物教程:萌萌的小仓鼠
  4. tick数据是怎样的
  5. 阿里高级面试官对javaMYsql面试提过的问题和最精准的答案
  6. 转:js 将json字符串转换为json对象的方法解析
  7. Java把文件压缩然后下载
  8. android 实现在照片上涂鸦
  9. 计算机用鼠标画图,cad画图用什么键盘好,画图工作合适的键盘鼠标
  10. mysql 上个月 汇总_还是问一个mysql的查询汇总的汇总问题