zoukankan      html  css  js  c++  java
  • #3790. 神奇项链 题解

    Description

    (bzoj) 上的题,黑暗爆炸OJ传送门

    Solution

    是一道 (manacher) 算法的应用题。

    首先转换一下题意:给定一个字符串,让我们求最少的回文串个数去覆盖它。

    所以先跑一遍 (manacher),求出每个回文串的左右边界,存到一个数组里。此时这道题就变成了让我们选出最少的区间覆盖 (1) ~ (n)

    一道非常经典的贪心,我们先按左端点排序,左端点相同的点按右端点排序。

    枚举区间时,记录一下最右边覆盖到哪里了,在所有当前合法的区间中选出右端点最靠右的区间,同时更新最右覆盖及合并次数即可(感觉说不清楚,具体看代码吧)。

    注意到 (aba)(aca) 可以合并为 (abaaca),所以判断时,要判断 (q[i].l - 1 <= maxr)

    Code

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 1e5 + 10;
    char str[N], s[N << 1];
    int n, p[N];
    struct node{
        int l, r;
        bool operator < (const node &b) const{
            return l != b.l ? l < b.l : r < b.r;
        }
    }a[N];
    
    inline void init(){
        n = strlen(str + 1);
        s[0] = '*', s[1] = '#';
        for(int i = 1; i <= n; i++)
            s[i << 1] = str[i], s[(i << 1) + 1] = '#';
        n = (n << 1) + 1;
    }
    
    inline void manacher(){
        int id = 0, mx = 0;
        for(int i = 1; i <= n; i++){
            if(i < mx) p[i] = min(p[(id << 1) - i], mx - i);
            else p[i] = 1;
            while(i - p[i] >= 1 && i + p[i] <= n && s[i - p[i]] == s[i + p[i]]) p[i]++;
            if(i + p[i] > mx) id = i, mx = i + p[i];
        }
    }
    
    inline int solve(){
        memset(p, 0, sizeof(p));
        init();
        manacher();
        for(int i = 1; i <= n; ++i)
            a[i].l = i - p[i] + 1, a[i].r = i + p[i] - 1;
        sort(a + 1, a + 1 + n);
        int r = 0, mx = 0, cnt = 0;
        for(int i = 1; i <= n;){
            if(a[i].l - 1 <= r) mx = max(mx, a[i].r), ++i;
            else r = mx, mx = 0, cnt++;
        }
        cnt += (r < n);
        return cnt - 1;
    }
    
    int main(){
        while(scanf("%s", str + 1) != EOF)
            printf("%d
    ", solve());
        return 0;
    }
    

    End

    本文来自博客园,作者:xixike,转载请注明原文链接:https://www.cnblogs.com/xixike/p/15407183.html

  • 相关阅读:
    python学习笔记(29)-操作excel
    python学习笔记(28)-unittest单元测试-执行用例
    python学习笔记(27)-unittest单元测试-测试用例
    python学习笔记(26)-request模块
    python学习笔记(25)-继承
    c++ 流基本概念
    友元函数、类和运算符重载
    c++中的引用
    c++重点知识点
    指针和结构体
  • 原文地址:https://www.cnblogs.com/xixike/p/15407183.html
Copyright © 2011-2022 走看看