http://www.lydsy.com/JudgeOnline/problem.php?id=1396
Solution:
我得了“能用后缀数组就一定不用后缀自动机综合症”….感觉用height、rank、sa 处理字符串真的好优雅….
虽然其他题上后缀数组常数比较大…不过这个后缀数组水了一发似乎就Rank1 了…开心
题解就是求出后缀数组以后维护一个单调队列来更新答案啦。。。
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define rep(i, x, y) for (int i = (x), _ = (y); i <= _; ++i)
#define down(i, x, y) for (int i = (x), _ = (y); i >= _; --i)
#define x first
#define y second
#define LX_JUDGE
using namespace std;
typedef long long LL;
template<typename T> inline void up_max(T & x, T y) { x < y ? x = y : 0; }
template<typename T> inline void up_min(T & x, T y) { x > y ? x = y : 0; }
template<typename T>
inline void read(T & x)
{
char c;
while ((c = getchar()) < '0' || c > '9') ;
for (x = c - '0'; (c = getchar()) >= '0' && c <= '9'; x = x * 10 + c - '0') ;
}
const int inf = 0x3f3f3f3f ;
const int N = 1e5 + 10;
namespace Suffix_Array
{
int Sa[N], Rank[N], height[N];
void Suffix_Da(char * r, int n, int m)
{
static int ws[N];
int i, j, p, *x = Rank, *y = height;
memset(ws, 0, sizeof(int) * m);
for (i = 0; i < n; ++i)
++ws[x[i] = r[i]];
for (i = 1; i < m; ++i)
ws[i] += ws[i - 1];
for (i = n - 1; ~i; --i)
Sa[--ws[x[i]]] = i;
for (j = p = 1; p < n; j <<= 1, m = p)
{
for (p = 0, i = n - j; i < n; ++i)
y[p++] = i;
for (i = 0; i < n; ++i) if (Sa[i] >= j)
y[p++] = Sa[i] - j;
memset(ws, 0, sizeof(int) * m);
for (i = 0; i < n; ++i)
++ws[x[i]];
for (i = 1; i < m; ++i)
ws[i] += ws[i - 1];
for (i = n - 1; ~i; --i)
Sa[--ws[x[y[i]]]] = y[i];
swap(x, y);
x[Sa[0]] = 0, p = 1;
for (i = 1; i < n; ++i)
x[Sa[i]] = (y[Sa[i - 1]] == y[Sa[i]] && y[Sa[i - 1] + j] == y[Sa[i] + j]) ? p - 1 : p++;
}
for (i = 0; i < n; ++i)
Rank[Sa[i]] = i;
for (p = 0, i = 0; i < n - 1; ++i)
{
p ? --p : 0;
j = Sa[Rank[i] - 1];
while (r[i + p] == r[j + p])
++p;
height[Rank[i]] = p;
}
height[n] = height[0] = height[1] = 0;
}
}
namespace My_Worker
{
typedef pair<int , int> Data;
Data que[N];
int left = 1, right = 0;
void insert(Data u)
{
while (left <= right && u.y - u.x <= que[right].y - que[right].x)
--right;
que[++right] = u;
}
int query(int x)
{
#define calc(o) (max((o).y, x) - (o).x + 1)
while (left < right && calc(que[left + 1]) <= calc(que[left]))
++left;
return calc(que[left]);
#undef calc
}
}
char str[N];
int main()
{
#ifdef LX_JUDGE
freopen("in.txt", "r", stdin);
#endif
using namespace Suffix_Array;
using namespace My_Worker;
scanf("%s", str);
int n = strlen(str);
str[n++] = 0;
Suffix_Da(str, n, 128);
rep (i, 0, n - 2)
{
int tmp = i + max(height[Rank[i]], height[Rank[i] + 1]);
if (tmp < n - 1)
insert(Data(i, tmp));
printf("%d\n", query(i));
}
return 0;
}
本文分享了一个使用后缀数组解决字符串匹配问题的实际案例。通过分析题目要求,采用后缀数组结合单调队列的方法,有效地解决了问题,并给出了完整的代码实现。

140

被折叠的 条评论
为什么被折叠?



