#include<bits/stdc++.h> using namespace std; const int N = 2e5; const int MAX_CHAR = 255;//每个数字的最大值。 char s[N + 10];//如果是数字,就写成int s[N+10]就好,从0开始存 int Sa[N + 10], T1[N + 10], T2[N + 10], C[N+10]; //Rank数组下标是从0开始的,表示的是从i开始的后缀的排名 //Sa数组又是从1开始的,表示的是第i名的(i>=1)后缀是从字符串中的第几个字符开始的. int Height[N + 10], Rank[N + 10]; void build_Sa(int n, 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]; for (i = n - 1; i >= 0; i--) Sa[--C[x[i]]] = i; for (int k = 1; k <= n; k <<= 1) { int p = 0; 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; 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]; swap(x, y); p = 1; x[Sa[0]] = 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 n) { int i, j, k = 0; for (i = 1; i <= n; i++) Rank[Sa[i]] = i; for (i = 0; i<n; i++) { if (k) k--; j = Sa[Rank[i] - 1]; while (s[i + k] == s[j + k]) k++; Height[Rank[i]] = k; } } int main() { int i, n; while (scanf("%s", s) != EOF) { int len = strlen(s); s[len] = (int)('z') + 1; scanf("%s", s + len + 1); n = strlen(s),s[n] = 0; build_Sa(n + 1, MAX_CHAR);//注意调用n+1 getHeight(n); int ma = 0; for (i = 2; i <= n; i++) if ((Sa[i - 1]<len && Sa[i]>len) || (Sa[i - 1] > len && Sa[i] < len)) ma = max(ma, Height[i]); printf("%d\n", ma); } return 0; }
【hdu 1403】Longest Common Substring
转载
【链接】h在这里写链接
【题意】
【题解】
【反思】
【代码】
求两个串的最长公共子串。
Sa[i]表示的是字典序为i的后缀的起始位置。
可以把两个字符串合在一起(中间用一个比'z'大的字符分割);
则如果Sa[i-1]<len1且Sa[i]>len1;
则它们表示s1和s2的两个后缀。
取height[i]然后求最大值就可以了。
(height[i]表示的是字典序为i-1和字典序为i的后缀它们的最长公共前缀)
在这里,也即两个子串了。
【错的次数】
5+
桶的大小得设置成2e5才行。。不是字符ascill码的最大值。。
本文章为转载内容,我们尊重原作者对文章享有的著作权。如有内容错误或侵权问题,欢迎原作者联系我们进行内容更正或删除文章。
提问和评论都可以,用心的回复会被更多人看到
评论
发布评论
相关文章
-
【后缀数组】 HDOJ 1403 Longest Common Substring
简单的后缀数组。。。先用倍增算法
HDU 后缀数组 #include i++ #define -
spoj Longest Common Substring II
SAM
#include #define 字符串 -
SPOJ LCS Longest Common Substring
DescriptionA string is finite sequence of
spoj #include i++ 初始化 -
SP1811 LCS - Longest Common Substring
题目链接:传送门求LCS可不是那个dp了SAM的板子题对一个串建SAM然后匹配
SAM SPOJ 字符串 省选 #include -
spoj1811 LCS - Longest Common Substring
分析 我们可以建出s串的parent树 然后t串在上面跳着找即可 代码
i++ #include c++ 题解 编程语言 学习