题意:输入2个长度不超过100000的字符串,问它们最长公共子串的长度。

题目链接:http://poj.org/problem?id=2774

——>>后缀数组!后缀数组!~从LJ的《训练指南》,到许智磊的论文+PPT,吉大的模版,学长的博客,这路还真不容易走。。。

最后决定用LJ《训练指南》的写法,感觉挺精辟的。

合并两个串,中间放一个特殊字符,根据条件(len为第一个串的长度,n为合并后串的长度):

(sa[i] >= 0 && sa[i] < len && sa[i-1] > len && sa[i-1] < n) || (sa[i-1] >= 0 && sa[i-1] < len && sa[i] > len && sa[i] < n)判断是否取height[i],取出最大值。

#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; const int maxn = 100000 * 2 + 10; char s[maxn], s2[maxn];
int sa[maxn], t1[maxn], t2[maxn], c[maxn], rak[maxn], height[maxn], n; void build_sa(int m){
int i, *x = t1, *y = t2;
//基数排序
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[i] = s[i]]++;
for(i = 1; i < m; i++) c[i] += c[i-1]; //预留空位给比c[i]小的字符
for(i = n-1; i >= 0; i--) sa[--c[x[i]]] = i; //从右往左,相等的从大号到小号 for(int k = 1; k < n; k <<= 1){ //每次判断时已算完了长度为k的后缀
int p = 0;
//直接用sa数组排序第二关键字
for(i = n-k; i < n; i++) y[p++] = i;
for(i = 0; i < n; i++) if(sa[i] >= k) y[p++] = sa[i] - k; //刚才是sa[i]位,倍增后左移变位于sa[i]-k位
//第二关键字排完序后已连成一条链,从端开始扫描就是
//基数排序第一关键字
for(i = 0; i < m; i++) c[i] = 0;
for(i = 0; i < n; i++) c[x[y[i]]]++;
for(i = 1; i < m; i++) c[i] += c[i-1];
for(i = n-1; i >= 0; i--) sa[--c[x[y[i]]]] = y[i]; //从右往左扫描y[i]是第二关键字从大到小,它应放到第一关键字相同的最右
//根据sa和y数组计算新的x数组
swap(x, y); //此时y数组变得没意义,但更新x数组又要用到原来的x数组,所以将原来的x数组存到y数组里
p = 1;
x[sa[0]] = 0; //(以下类似于离散化)最小的那1位赋0,接着开始从小到大扫描
for(i = 1; i < n; i++)
x[sa[i]] = y[sa[i-1]] == y[sa[i]] && y[sa[i-1]+k] == y[sa[i]+k] ? p-1 : p++;
if(p >= n) break;
m = p;
}
} void getHeight(){
int i, j, k = 0;
for(i = 0; i < n; i++) rak[sa[i]] = i;
height[0] = 0;
for(i = 0; i < n; i++){
if(!rak[i]) continue; //注意判空!
if(k) k--; //height[rank[i]] >= height[rank[i-1]] - 1
j = sa[rak[i]-1]; //等级比i小1的后缀编号为j
while(s[i+k] == s[j+k]) k++;
height[rak[i]] = k;
}
} void solve(){
int len = strlen(s);
s[len] = '$';
s[len+1] = '\0';
strcat(s, s2);
n = strlen(s);
build_sa(256);
getHeight();
int Max = -1, i;
for(i = 1; i < n; i++) if((sa[i] >= 0 && sa[i] < len && sa[i-1] > len && sa[i-1] < n) || (sa[i-1] >= 0 && sa[i-1] < len && sa[i] > len && sa[i] < n)) Max = max(Max, height[i]);
printf("%d\n", Max);
} int main()
{
while(scanf("%s%s", s, s2) == 2) solve();
return 0;
}

poj - 2774 - Long Long Message的更多相关文章

  1. POJ 2774 Long Long Message [ 最长公共子串 后缀数组]

    题目:http://poj.org/problem?id=2774 Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total ...

  2. [POJ 2774] Long Long Message 【后缀数组】

    题目链接:POJ - 2774 题目分析 题目要求求出两个字符串的最长公共子串,使用后缀数组求解会十分容易. 将两个字符串用特殊字符隔开再连接到一起,求出后缀数组. 可以看出,最长公共子串就是两个字符 ...

  3. POJ 2774 Long Long Message 后缀数组

    Long Long Message   Description The little cat is majoring in physics in the capital of Byterland. A ...

  4. poj 2774 Long Long Message 后缀数组基础题

    Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 24756   Accepted: 10130 Case Time Limi ...

  5. 后缀数组(模板题) - 求最长公共子串 - poj 2774 Long Long Message

    Language: Default Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 21 ...

  6. POJ 2774 Long Long Message(后缀数组)

    [题目链接] http://poj.org/problem?id=2774 [题目大意] 求最长公共子串 [题解] 将两个串中间嵌一个字符相连,求一遍后缀数组 如果排名相邻的两个后缀的开端是分属于两个 ...

  7. ●POJ 2774 Long Long Message

    题链: http://poj.org/problem?id=2774题解: 后缀自动机 使用后缀自动机匹配,思路如下: 即如果当前的x字符匹配失败了,就可以从当前已经匹配的串的后缀去继续匹配. 然后不 ...

  8. POJ 2774 Long Long Message (Hash + 二分)

    Long Long Message Time Limit: 4000MS   Memory Limit: 131072K Total Submissions: 34473   Accepted: 13 ...

  9. POJ 2774 Long Long Message&&HDU 1403 Longest Common Substring&&COJ 1203

    后缀数组的买1送2题... HDU的那题数据实在是太水了,后来才发现在COJ和POJ上都是WA..原因在一点:在建立sa数组的时候里面的n应该是字符串长度+1....不懂可以去看罗大神的论文... 就 ...

随机推荐

  1. NewtonPrincipia --- 公理或运动的定律 --- 系理二

    NewtonPrincipia --- 公理或运动的定律 --- 系理二 自然哲学的数学原理>公理或运动的定律>系理II 平行四边形ABCD,那么:直接的力AD由任意的力AB和BD合成,直 ...

  2. 批量还原数据库 SQL Server 2008

    1.如果你够懒,不想一步一步点路径,一步一步选择 2.如果你连单个备份数据库的存储过程都不想多执行,一般每还原一个需要修改数据库名 下面的脚本适合你: /*********************** ...

  3. UI控件入门

    其实整个学习过程.确实有点儿混乱,因为不懂的东西太多,一会儿看这,一会儿看那,马上就乱了. 还是先做点儿简单的事儿,说控件,但不会说完全,只是入个门,知道怎么学控件,具体要学好每一个控件需要项目中磨练 ...

  4. 算法:最大子数组own

    转载标明出处:http://i.cnblogs.com/EditPosts.aspx?postid=4726782&update=1 暴力法: // maxValue.cpp : 定义控制台应 ...

  5. delphi 集合

    DELPHI没有JAVA的丰富的集合(SET MAP LIST),只有Tlist,可包装各种类型

  6. <一道题>abc+cba=1333,求满足条件的abc的值,隐含条件a!=0,c!=0

    这类东西,无非就是穷举法.见下面代码: #include <stdio.h> #include <stdlib.h> /* *abc + cba = 1333 * *a = ? ...

  7. Dom操作的分类

    1.DOM core 使用DOM core来获取表单对象的方法: document.getElementByTagName("form"); 使用DOM Core来获取某元素的sr ...

  8. 求C#开发大神指点职业规划或者开发路数(以后怎么走),谢谢

    背景:作为一名Asp.net Web类的开发人员,工作时间有点长,5年不到,属于是天赋不太强,但是比较努力型的人,开发过程中那事情基本上都会,各种前后端框架也会使用.目前在研究分布式缓存应用 Memc ...

  9. hdoj 5399 Tpp simple

    WA了一下午.... 1WA:T了,因为阶乘没打表所以时间超了.. 2WA,3WA:runtime error,检查的value数组开小了,应该是MAXN.. 4WA.5WA.6WA:改了改对cnt的 ...

  10. 数据结构——图——最短路径D&F算法

    一.Dijkstra算法(贪心地求最短距离的算法) 在此算法中,我按照自己的理解去命名,理解起来会轻松一些. #define MAXSIZE 100 #define UNVISITED 0 #defi ...