leetcode 2213. 由单个字符重复的最长子字符串
本题2213 由单个字符重复的最长子字符串,可以用线段树和珂朵莉树解决,涉及到单点修改和区间查询,关键点在于单点修改后的区间分割与合并。
线段树方法
我是通过这篇博客学习线段树相关的知识,博主讲的很详细了,比较推荐。
class Solution {
public:
struct node
{
int l, r, pre, suf, max, size;
char lch, rch;
};
node t[400005];
string ss;
void update(int p, char v, int l, int r, int k)
{
if(l == r)
{
t[k].lch = t[k].rch = v;
}
else
{
int m = l + ((r-l)>>1);
if(p <= m)
update(p, v, l, m, k<<1);
else
update(p, v, m+1, r, k<<1|1);
merge(k);
}
}
void merge(int k)
{
t[k].l = t[k<<1].l;
t[k].r = t[k<<1|1].r;
t[k].size = t[k].r - t[k].l + 1;
t[k].lch = t[k<<1].lch;
t[k].rch = t[k<<1|1].rch;
if(t[k<<1].rch == t[k<<1|1].lch)
{
if(t[k<<1].suf == t[k<<1].size)
{
t[k].pre = t[k<<1].size + t[k<<1|1].pre;
}
else t[k].pre = t[k<<1].pre;
if(t[k<<1|1].pre == t[k<<1|1].size)
{
t[k].suf = t[k<<1].suf + t[k<<1|1].size;
}
else t[k].suf = t[k<<1|1].suf;
t[k].max = max(t[k<<1].max, t[k<<1|1].max);
t[k].max = max(t[k].max, max(t[k].pre, t[k].suf));
t[k].max = max(t[k].max, t[k<<1].suf + t[k<<1|1].pre);
}
else
{
t[k].pre = t[k<<1].pre;
t[k].suf = t[k<<1|1].suf;
t[k].max = max(t[k<<1].max, t[k<<1|1].max);
}
}
void build(int l, int r, int k)
{
if(l == r)
{
t[k].l = t[k].r = l;
t[k].lch = t[k].rch = ss[l];
t[k].suf = t[k].pre = 1;
t[k].size = t[k].max = 1;
}
else
{
int m = l + ((r-l) >> 1);
build(l, m, k<<1);
build(m+1, r, k<<1|1);
merge(k);
}
}
vector<int> longestRepeating(string s, string queryCharacters, vector<int>& queryIndices) {
vector<int> ans;
ss = "0" + s;
int n = s.size();
build(1, n, 1);
for(int i = 0; i < queryCharacters.size(); ++i)
{
update(queryIndices[i]+1, queryCharacters[i], 1, n, 1);
ans.push_back(t[1].max);
}
return ans;
}
};
珂朵莉树方法
线段树之前就听说过,但以前只是会用模板,这次好好学习了一下。但是看到珂朵莉树就有点懵了,为什么数据结构和动漫可以扯上关系,原来这种数据结构来源于cf上的一道题的题解,题目就是有关动漫的,珂朵莉应该就是女主了。这种数据结构是通过多个集合维护不同的区间,可以参考这篇博客。
class Solution {
public:
struct node
{
mutable int l, r, len;
char ch;
bool operator < (const node& rhs) const
{
return l < rhs.l;
}
node(int a = -1, int b = -1, int c = 0, char d = '0'){
l=a,r=b,len=c,ch=d;
}
};
set<node> st;
multiset<int> nodelen;
set<node>::iterator split(int pos)
{
set<node>::iterator it = st.lower_bound(node(pos));
if(it != st.end() && it->l == pos) return it;
--it;node tmp = *it;st.erase(it);
nodelen.erase(nodelen.find(tmp.len));
nodelen.insert(pos - tmp.l);
nodelen.insert(tmp.r-pos+1);
st.insert(node(tmp.l, pos-1, pos - tmp.l, tmp.ch));
return st.insert(node(pos, tmp.r, tmp.r - pos + 1, tmp.ch)).first;
}
void assign(int p, char ch)
{
set<node>::iterator spr = split(p+1), spl = split(p);
st.erase(spl, spr);
set<node>::iterator it = st.insert(node(p, p, 1, ch)).first;
if(it != st.begin())
{
set<node>::iterator itl = it;
--itl;
if(itl->ch == it->ch)
{
nodelen.erase(nodelen.find(itl->len));
nodelen.erase(nodelen.find(it->len));
it->l = itl->l;
it->len = it->len + itl->len;
nodelen.insert(it->len);
st.erase(itl);
}
}
if(it != st.end())
{
set<node>::iterator itr = it;
++itr;
if(itr != st.end() && itr->ch == it->ch)
{
nodelen.erase(nodelen.find(itr->len));
nodelen.erase(nodelen.find(it->len));
it->r = itr->r;
it->len = it->len + itr->len;
nodelen.insert(it->len);
st.erase(itr);
}
}
}
vector<int> longestRepeating(string s, string queryCharacters, vector<int>& queryIndices) {
char now = s[0];
int cnt = 1;
vector<int> ans;
int n = s.size();
for(int i = 1; i < n; ++i)
if(s[i] == now)
{
cnt++;
}
else
{
st.insert(node(i-cnt, i-1, cnt, now));
nodelen.insert(cnt);
now = s[i];
cnt = 1;
}
st.insert(node(n-cnt, n-1, cnt, now));
nodelen.insert(cnt);
for(int i = 0; i < queryCharacters.size(); ++i)
{
assign(queryIndices[i], queryCharacters[i]);
ans.push_back(*nodelen.rbegin());
}
return ans;
}
};
ps:这部番评价很好,之后可以补番了。