学习到的内容 : 初步了解并使用trie树, 初步了解了离线算法
对于扣问的区间的字符串建一个trie树的话, 每个节点(除去根节点, 或者是边数)走两次, 最长的字符串不消回退, 答案就是 节点数 * 2 - 最长串的长度
求每次扣问区间形成的trie树, 可以用离线算法, 给扣问r端点排序, 这时只必要减去左边不包含的区间的节点就行了. 对于重复的边, 每次都让他盘算为新来的字符串的长度, 不盘算为以前的字符串的长度
- #include<bits/stdc++.h>
- using namespace std;
- using i64 = long long;
- template <typename T>
- struct Fenwick {
- int n;
- std::vector<T> a;
-
- Fenwick(int n_ = 0) {
- init(n_);
- }
-
- void init(int n_) {
- n = n_;
- a.assign(n, T{});
- }
-
- void add(int x, const T &v) {
- for (int i = x; i <= n; i += i & -i) {
- a[i] = a[i] + v;
- }
- }
-
- T sum(int x) {
- T ans{};
- for (int i = x; i > 0; i -= i & -i) {
- ans = ans + a[i];
- }
- return ans;
- }
-
- T rangeSum(int l, int r) {
- return sum(r) - sum(l - 1);
- }
-
- };
- Fenwick<int> fenwick(1000001);
- int nex[1000001][26], tot;
- int cnt[1000001]; // 该结点结尾的字符串的数量
- int belongto[1000001];
- struct Trie {
-
- void insert(string s, int idx, int t = 1) { // 插入字符串
- int p = 0;
- for (int i = 0; i < s.length(); i++) {
- int c = s[i] - 'a';
- if (!nex[p][c]) nex[p][c] = ++tot; // 如果没有,就添加结点
- p = nex[p][c];
- ;
- if(belongto[p]) fenwick.add(belongto[p], -1);
- belongto[p] = idx;
- fenwick.add(belongto[p], 1);
- }
- cnt[p] += t;
- }
- bool find(string s) { // 查找字符串
- int p = 0;
- for (int i = 0; i < s.length(); i++) {
- int c = s[i] - 'a';
- if (!nex[p][c]) return 0;
- p = nex[p][c];
- }
- return cnt[p];
- }
- };
- template<class Info>
- struct SegmentTree {
- int n;
- std::vector<Info> info;
- SegmentTree() : n(0) {}
- SegmentTree(int n_, Info v_ = Info()) {
- init(n_, v_);
- }
- template<class T>
- SegmentTree(std::vector<T> init_) {
- init(init_);
- }
- void init(int n_, Info v_ = Info()) {
- init(std::vector(n_, v_));
- }
- template<class T>
- void init(std::vector<T> init_) {
- n = init_.size();
- info.assign(4 << std::__lg(n), Info());
- std::function<void(int, int, int)> build = [&](int p, int l, int r) {
- if (r - l == 1) {
- info[p] = init_[l];
- return;
- }
- int m = (l + r) / 2;
- build(2 * p, l, m);
- build(2 * p + 1, m, r);
- pull(p);
- };
- build(1, 0, n);
- }
- void pull(int p) {
- info[p] = info[2 * p] + info[2 * p + 1];
- }
- void modify(int p, int l, int r, int x, const Info &v) {
- if (r - l == 1) {
- info[p] = v;
- return;
- }
- int m = (l + r) / 2;
- if (x < m) {
- modify(2 * p, l, m, x, v);
- } else {
- modify(2 * p + 1, m, r, x, v);
- }
- pull(p);
- }
- void modify(int p, const Info &v) {
- modify(1, 1, n, p, v);
- }
- Info rangeQuery(int p, int l, int r, int x, int y) {
- if (l >= y || r <= x) {
- return Info();
- }
- if (l >= x && r <= y) {
- return info[p];
- }
- int m = (l + r) / 2;
- return rangeQuery(2 * p, l, m, x, y) + rangeQuery(2 * p + 1, m, r, x, y);
- }
- Info rangeQuery(int l, int r) {
- return rangeQuery(1, 1, n, l, r + 1);
- }
- template<class F>
- int findFirst(int p, int l, int r, int x, int y, F &&pred) {
- if (l >= y || r <= x) {
- return -1;
- }
- if (l >= x && r <= y && !pred(info[p])) {
- return -1;
- }
- if (r - l == 1) {
- return l;
- }
- int m = (l + r) / 2;
- int res = findFirst(2 * p, l, m, x, y, pred);
- if (res == -1) {
- res = findFirst(2 * p + 1, m, r, x, y, pred);
- }
- return res;
- }
- template<class F>
- int findFirst(int l, int r, F &&pred) {
- return findFirst(1, 1, n, l, r + 1, pred);
- }
- template<class F>
- int findLast(int p, int l, int r, int x, int y, F &&pred) {
- if (l >= y || r <= x) {
- return -1;
- }
- if (l >= x && r <= y && !pred(info[p])) {
- return -1;
- }
- if (r - l == 1) {
- return l;
- }
- int m = (l + r) / 2;
- int res = findLast(2 * p + 1, m, r, x, y, pred);
- if (res == -1) {
- res = findLast(2 * p, l, m, x, y, pred);
- }
- return res;
- }
- template<class F>
- int findLast(int l, int r, F &&pred) {
- return findLast(1, 1, n, l, r + 1, pred);
- }
- };
- constexpr int inf = 1E9 + 1;
- struct Info {
- int max = -inf;
- int min = inf;
- };
- Info operator+(const Info &a, const Info &b) {
- return { std::max(a.max, b.max), std::min(a.min, b.min) };
- }
- struct qur {
- int l, idx;
- };
- void solve(){
-
- int n, m;
- cin >> n >> m;
-
- vector<string> s(n + 1);
- SegmentTree<Info> maxlen(n + 1);
- for(int i = 1; i <= n; i++) cin >> s[i], maxlen.modify(i, {(int)s[i].length(),(int)s[i].length()});
- vector<vector<qur>> xun(n + 1);
- for(int i = 1; i <= m; i++) {
- int l, r;
- cin >> l >> r;
- xun[r].push_back({l, i});
- }
- Trie trie;
- vector<int> ans(m + 1);
- for(int i = 1; i <= n; i++) {
- trie.insert(s[i], i);
- for(auto it : xun[i]) {
- int l = it.l, idx = it.idx;
- auto mxln = maxlen.rangeQuery(l, i).max;
- ans[idx] = fenwick.rangeSum(l, i) * 2 - mxln;
- }
- }
- for(int i = 1; i <= m; i++) cout << ans[i] << endl;
-
- }
- int main(){
- std::ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
- int T = 1;
- //cin >> T;
- // cout << 1 << endl;
- while(T--) solve();
- return 0;
- }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |