[poj 2274]后缀数组+最长公共子串
题目链接:http://poj.org/problem?id=2774
后缀数组真的太强大了,原本dp是O(nm)的复杂度,在这里只需要O(n+m)。
做法:将两个串中间夹一个未出现过的字符接起来,然后做一次后缀数组,得到的height相邻两个排名的后缀,在串中的位置如果满足在分界符左右两侧,就更新最长公共前缀。最后得到的最大值就是最长公共子序列。
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std; const int MAXN = *;
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int wa[MAXN*],wb[MAXN*],wv[MAXN*],wss[MAXN*];
int c0(int *r,int a,int b)
{
return r[a] == r[b] && r[a+] == r[b+] && r[a+] == r[b+];
}
int c12(int k,int *r,int a,int b)
{
if(k == )
return r[a] < r[b] || ( r[a] == r[b] && c12(,r,a+,b+) );
else return r[a] < r[b] || ( r[a] == r[b] && wv[a+] < wv[b+] );
}
void sort(int *r,int *a,int *b,int n,int m)
{
int i;
for(i = ; i < n; i++)wv[i] = r[a[i]];
for(i = ; i < m; i++)wss[i] = ;
for(i = ; i < n; i++)wss[wv[i]]++;
for(i = ; i < m; i++)wss[i] += wss[i-];
for(i = n-; i >= ; i--)
b[--wss[wv[i]]] = a[i];
}
void dc3(int *r,int *sa,int n,int m)
{
int i, j, *rn = r + n;
int *san = sa + n, ta = , tb = (n+)/, tbc = , p;
r[n] = r[n+] = ;
for(i = ; i < n; i++)if(i % != )wa[tbc++] = i;
sort(r + , wa, wb, tbc, m);
sort(r + , wb, wa, tbc, m);
sort(r, wa, wb, tbc, m);
for(p = , rn[F(wb[])] = , i = ; i < tbc; i++)
rn[F(wb[i])] = c0(r, wb[i-], wb[i]) ? p - : p++;
if(p < tbc)dc3(rn,san,tbc,p);
else for(i = ; i < tbc; i++)san[rn[i]] = i;
for(i = ; i < tbc; i++) if(san[i] < tb)wb[ta++] = san[i] * ;
if(n % == )wb[ta++] = n - ;
sort(r, wb, wa, ta, m);
for(i = ; i < tbc; i++)wv[wb[i] = G(san[i])] = i;
for(i = , j = , p = ; i < ta && j < tbc; p++)
sa[p] = c12(wb[j] % , r, wa[i], wb[j]) ? wa[i++] : wb[j++];
for(; i < ta; p++)sa[p] = wa[i++];
for(; j < tbc; p++)sa[p] = wb[j++];
}
void da(int str[],int sa[],int rank[],int height[],int n,int m)
{
for(int i = n; i < n*; i++)
str[i] = ;
dc3(str, sa, n+, m);
int i,j,k = ;
for(i = ; i <= n; i++)rank[sa[i]] = i;
for(i = ; i < n; i++)
{
if(k) k--;
j = sa[rank[i]-];
while(str[i+k] == str[j+k]) k++;
height[rank[i]] = k;
}
} int str[MAXN*],sa[MAXN*],rk[MAXN],height[MAXN]; char s1[MAXN],s2[MAXN];
int l1,l2; int main()
{
while (~scanf("%s%s",s1,s2))
{
l1=strlen(s1);
l2=strlen(s2);
for (int i=; i<l1; i++) str[i]=s1[i]-'a'+;
str[l1]=;
for (int i=;i<l2;i++) str[l1++i]=s2[i]-'a'+;
str[l1+l2+]=;
da(str,sa,rk,height,l1+l2+,);
int ma=;
for (int i=;i<=l1+l2+;i++)
{
int p1=sa[i-];
int p2=sa[i];
if (p1<l1&&p2>l1 || p1>l1&&p2<l1) ma=max(ma,height[i]);
}
printf("%d\n",ma);
}
return ;
}
[poj 2274]后缀数组+最长公共子串的更多相关文章
- POJ 2217 (后缀数组+最长公共子串)
题目链接: http://poj.org/problem?id=2217 题目大意: 求两个串的最长公共子串,注意子串是连续的,而子序列可以不连续. 解题思路: 后缀数组解法是这类问题的模板解法. 对 ...
- POJ-2774-Long Long Message(后缀数组-最长公共子串)
题意: 给定两个字符串 A 和 B,求最长公共子串. 分析: 字符串的任何一个子串都是这个字符串的某个后缀的前缀. 求 A 和 B 的最长公共子串等价于求 A 的后缀和 B 的后缀的最长公共前缀的最大 ...
- POJ3294 Life Forms —— 后缀数组 最长公共子串
题目链接:https://vjudge.net/problem/POJ-3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total ...
- POJ 2774 (后缀数组 最长公共字串) Long Long Message
用一个特殊字符将两个字符串连接起来,然后找最大的height,而且要求这两个相邻的后缀的第一个字符不能在同一个字符串中. #include <cstdio> #include <cs ...
- POJ 3294 Life Forms [最长公共子串加强版 后缀数组 && 二分]
题目:http://poj.org/problem?id=3294 Life Forms Time Limit: 5000MS Memory Limit: 65536K Total Submiss ...
- poj 1458 Common Subsequence_最长公共子串
题意:略 求最长公共子串 #include<iostream> #include<cstdio> #include<string> using namespace ...
- POJ3415 Common Substrings —— 后缀数组 + 单调栈 公共子串个数
题目链接:https://vjudge.net/problem/POJ-3415 Common Substrings Time Limit: 5000MS Memory Limit: 65536K ...
- CSU1632Repeated Substrings(后缀数组/最长公共前缀)
题意就是求一个字符串的重复出现(出现次数>=2)的不同子串的个数. 标准解法是后缀数组.最长公共前缀的应用,对于样例aabaab,先将所有后缀排序: aab 3 aabaab 1 a ...
- POJ3450 Corporate Identity —— 后缀数组 最长公共子序列
题目链接:https://vjudge.net/problem/POJ-3450 Corporate Identity Time Limit: 3000MS Memory Limit: 65536 ...
随机推荐
- C语言学习记录_2019.01.29
C语言的灵魂:指针 #include <stdio.h> int main(int argc, char **argv) { printf("Hello, World!\n&q ...
- STL——vector和list
vector和list为STL中的顺序容器,顺序容器会依次维护第一个到最后一个元素,在顺序容器上,我们主要的操作就是迭代. 头文件: #include<vector> #include&l ...
- mybatis报表,动态列与查询参数+行列转换
这是报表原型,在这张报表中,使用了动态的列与动态查询参数,动态列与动态查询参数全部使用map将参数传入 map参数: //拼接查询时间 for (String month : monthList) { ...
- R语言绘图:时间序列分析
ggplot2绘制 arima诊断图 library(ggfortify) autoplot(acf(gold[,2], plot = FALSE)) ggtsdiag(auto.arima(gold ...
- spring boot 中文文档地址
spring boot 中文文档地址 http://oopsguy.com/documents/springboot-docs/1.5.4/index.html Spring Boot 参考指 ...
- C++学习007-使用exit退出进程
使用exit可以实现退出当前进程. 如下 在程序接收到一个字符后,就退出进程 编写环境 vs2015 int main() { int a = 10, b = 20; std::cout <&l ...
- python正则-字符串处理,主要用于处理请求参数格式为application/x-www-form-urlencoded的表单数据
#当提交的表单数据格式为application/x-www-form-urlencoded,直接从浏览器复制出来的格式是str_lin(chrome,也是最常见的)或者str_in2(火狐)这两种格式 ...
- 【Linux运维】Centos7上借助ansible搭建LVS+Keepalived
安装ansible 安装ansible: [root@localhost ~]# /etc/hosts 192.168.19.129 web129.yanglt.com web129 192.168. ...
- 问题 A: 完数
问题 A: 完数 时间限制: 1 Sec 内存限制: 32 MB提交: 252 解决: 178[提交][状态][讨论版][命题人:外部导入] 题目描述 求1-n内的完数,所谓的完数是这样的数,它的 ...
- ubuntu中 VI 方向键、删除键问题
这两天重新装的ubuntu系统,发觉使用VI时,方向键按下去后变成ABCD,删除键无效.网上搜寻一番,应该是VI软件本身的问题,顾卸载重装即可,步骤如下: 1.执行命令 sudo apt-get re ...