第一题
目前还没做出来,竟然是离线打好表,然后把数据复制到代码的数组里
第二题
跟上次一样是后缀数组
B. 田田背课文 2014新生暑假个人排位赛11
时间限制 10000 ms
内存限制 65536 KB
题目描述
田田被老师要求背诵一个字符串,田田刚刚背了一个子串,说他记性差他还不承认,背下这个子串后却忘了这个子串是从哪里开始的。
现在田田把这个字符串给你,并且让你告诉他至少一次背多长的子串才不可能产生歧义,即不存在另一个子串与它相等
输入格式
输入仅一行,即要求田田背诵的字符串
长度<=10^6
输出格式
输出一行,即不产生歧义串的最小串长
输入样例
abcdabcd
输出样例
5
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <vector>
#include <algorithm>
#include <cstring>
#include <cmath>
#define maxn 1000007
using
namespace
std;
int
n, k;
int
r[maxn];
int
tmp[maxn];
int
lcp[maxn];
int
sa[maxn];
string s;
bool
compare_sa(
int
i,
int
j)
{
if
(r[i]!=r[j])
return
r[i]<r[j];
else
{
int
ri = i+k<=n?r[i+k]:0;
int
rj = j+k<=n?r[j+k]:0;
return
ri<rj;
}
}
void
construct_sa()
{
for
(
int
i=0; i<=n; i++)
{
sa[i]=i;
r[i] = s[i];
}
int
tot;
for
(k=1; k<=n ;k<<=1)
{
sort(sa, sa+n+1, compare_sa);
tot = 0;
tmp[sa[0]] = 0;
for
(
int
i=1; i<=n; i++)
{
if
(compare_sa(sa[i-1], sa[i])) tmp[sa[i]] = ++tot;
else
tmp[sa[i]] = tot;
}
for
(
int
i=0; i<=n; i++)
r[i] = tmp[i];
if
(tot>=n)
break
;
}
}
void
construct_lcp()
{
for
(
int
i=0; i<=n; i++)
{
r[sa[i]] = i;
}
int
h = 0;
lcp[0] = 0;
for
(
int
i=0; i<n; i++)
{
if
(h>0)
lcp[i] = --h;
else
{
int
j=sa[r[i]-1];
for
(h=0; j+h<n&&i+h<n; h++)
if
(s[j+h] != s[i+h])
break
;
lcp[i] = h;
}
}
}
int
main()
{
cin >> s;
n=s.length();
//printf("%d\n", s[n]);
construct_sa();
construct_lcp();
int
ans = 0;
for
(
int
i=0; i<n; i++)
ans = max(ans, lcp[i]);
printf
(
"%d\n"
, ans+1);
return
0;
}
第三题