您的位置:首页 > 其它

[BZOJ 1396] 识别子串

2016-05-14 21:07 253 查看
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
, Rank
, height
;

void Suffix_Da(char * r, int n, int m)
{
static int ws
;
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
= height[0] = height[1] = 0;
}
}

namespace My_Worker
{
typedef pair<int , int> Data;

Data que
;
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
;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: