题目链接:https://leetcode-cn.com/problems/last-substring-in-lexicographical-order/
题意
给出一个字符串,求其字典序最大的子串
n
<
=
1
0
5
n<=10^5
n<=105
题解
解法1:
直接构建后缀自动机/后缀数组,直接跑即可,复杂度
O
(
n
∗
26
)
O(n*26)
O(n∗26)
解法2:
考虑到只需要对比所有后缀,其实就是后缀排序,但只需要找到最大值,所以用双指针枚举后缀,因为长的子串在一直相同的情况一定比短的子串大,所以维护两个起始点判定,如果后面的子串更大就把起始点往后移
维护两个起始点指针L,R,并往后枚举k位相同
1.
s
[
L
+
k
]
=
=
s
[
R
+
k
]
s[L+k]==s[R+k]
s[L+k]==s[R+k]:继续判断
2.
s
[
L
]
<
S
[
R
+
k
]
s[L]<S[R+k]
s[L]<S[R+k]:找到更大的起始点,直接把L移动到R+k
3.
s
[
L
+
k
]
<
s
[
R
+
k
]
s[L+k]<s[R+k]
s[L+k]<s[R+k]:右侧子串更大,把L移动到R,R移动到R+1
4.
s
[
L
+
k
]
>
s
[
R
+
k
]
s[L+k]>s[R+k]
s[L+k]>s[R+k]:左侧子串更大,令R++,重新匹配
code
1.SAM解法
#define ms(a) memset(a, 0, sizeof(a))
const int N = 800001;
const int base = 26;
int tr[N][base]; //base很大时使用umap
int link[N];
int len[N];
int cntp = 0;
int last = 0;
void init()
{
len[0] = 0;
ms(tr[0]);
last = 0;
link[0] = -1;
cntp = 0;
}
int addp()
{
int res = ++cntp;
//is_clo[res] = 0;
ms(tr[res]);
return res;
}
int clone(int p, int q)
{
int res = addp();
len[res] = len[p] + 1;
memcpy(tr[res], tr[q], sizeof(tr[res]));
link[res] = link[q];
return res;
}
void insert(int ch)
{
int cur = addp();
int p = last, q;
last = cur;
len[cur] = len[p] + 1;
while (p != -1 && !tr[p][ch])
{
tr[p][ch] = cur;
p = link[p];
}
if (p == -1)
{
link[cur] = 0;
return;
}
q = tr[p][ch];
if (len[q] == len[p] + 1)
{
link[cur] = q;
return;
}
int clo = clone(p, q);
while (p != -1 && tr[p][ch] == q)
{
tr[p][ch] = clo;
p = link[p];
}
link[q] = link[cur] = clo;
}
class Solution
{
public:
string lastSubstring(string s)
{
init();
int n = s.length();
for (int i = 0; i < n; i++)
{
insert(s[i] - 'a');
}
string res;
int p = 0;
while (1)
{
int flag = 0;
for (int i = 25; i >= 0; i--)
{
if (tr[p][i])
{
res.push_back(i + 'a');
p = tr[p][i];
flag = 1;
break;
}
}
if (!flag)
break;
}
return res;
}
};
2.双指针解法
class Solution {
public:
string lastSubstring(string s)
{
int L = 0, R = 1, k = 0, n = s.size();
while(R + k < n)
{
if(s[L + k] == s[R + k])
k++;
else if(s[L] < s[R + k])
{
L = R + k;
R = L + 1;
k = 0;
}
else if(s[L + k] < s[R + k])
{
L = R;
R++;
k = 0;
}
else
{
R++;
k = 0;
}
}
return s.substr(L);
}
};