SA例题

题面

对于串 \(S\) 的两个子串 \(A\) 和 \(B\) ,满足 \(k = |A| = |B|\),\(\exists c \forall i\, a_i + c=b_i\),且 \(A\) 和 \(B\) 在原串中没有重叠,求最大的满足条件的 \(k\)

先考虑 \(\forall i\, a_i=b_i\) 的情况,二分 \(k\) ,如果在\(height\)上存在一段满足 \(\forall L \le i \le R \,height_i\ge k\),且存在 \(SA[p_1]-SA[p_2] \ge k\),说明 \(k\) 满足条件

接下来将上述做法用在原数组的差分数组上即可,注意判定时条件要改为\(SA[p_1]-SA[p_2] > k\),且要在第一个字符前添加特殊字符,否则判定时可能出问题

#include<cstdio>
using namespace std;

const int MAXN = 5001;
int str[MAXN], sa[MAXN], rank[MAXN], ht[MAXN], buc[MAXN];

void Swap(int*& a, int*& b){
    int *tmp = a; a = b; b = tmp;
}

void getSA(int s[], int len){
    int *rk = rank, *tp = ht;
    int crd = 180, p;
    for (int i = 1; i <= len; ++i)
        rk[i] = s[i], tp[i] = i;
    for (int i = 0; i <= crd; ++i)
        buc[i] = 0;
    for (int i = 1; i <= len; ++i)
        ++buc[rk[i]];
    for (int i = 1; i <= crd; ++i)
        buc[i] += buc[i - 1];
    for (int i = len; i >= 1; --i)
        sa[buc[rk[tp[i]]]--] = tp[i];
    for (int w = 1; p != len; w <<= 1, crd = p){
        p = 0;
        for (int i = len - w + 1; i <= len; ++i)
            tp[++p] = i;
        for (int i = 1; i <= len; ++i)
            if (sa[i] > w)
                tp[++p] = sa[i] - w;
        for (int i = 0; i <= crd; ++i)
            buc[i] = 0;
        for (int i = 1; i <= len; ++i)
            ++buc[rk[i]];
        for (int i = 1; i <= crd; ++i)
            buc[i] += buc[i - 1];
        for (int i = len; i >= 1; --i)
            sa[buc[rk[tp[i]]]--] = tp[i];
        Swap(rk, tp);
        rk[sa[1]] = p = 1;
        for (int i = 2; i <= len; ++i)
            rk[sa[i]] = tp[sa[i]] == tp[sa[i - 1]] && tp[sa[i] + w] == tp[sa[i - 1] + w] ? p : ++p;
    }
    for (int i = 1; i <= len; ++i)
        rank[sa[i]] = i;
}

void getHeight(int s[], int len){
    ht[1] = 0;
    for (int i = 1, j = 0, pos; i <= len; ++i, --j){
        if (rank[i] == 1)
            continue;
        if (j < 0)
            j = 0;
        pos = sa[rank[i] - 1];
        while (s[i + j] == s[pos + j] && i + j <= len && pos + j <= len)
            ++j;
        ht[rank[i]] = j;
    }
}

bool judge(int k, int len){
    int lp, rp;
    for (int i = 1, j; i < len;){
        if (ht[i + 1] >= k){
            lp = rp = sa[i];
            j = i + 1;
            while (ht[j] >= k && j <= len){
                if (sa[j] < lp)
                    lp = sa[j];
                if (sa[j] > rp)
                    rp = sa[j];
                ++j;
            }
            if (rp - lp > k)
                return 1;
            i = j;
        }
        else
            ++i;
    }
    return 0;
}

int main(){
    int slen;
    scanf("%d", &slen);
    for (int i = 1, pre = 89, tmp; i <= slen; ++i){
        scanf("%d", &tmp);
        str[i] = tmp - pre + 89; pre = tmp;
    }
    getSA(str, slen);
    getHeight(str, slen);
    int L = 1, R = slen >> 1, mid;
    while (L + 1 < R){
        mid = L + R >> 1;
        if (judge(mid, slen))
            L = mid;
        else
            R = mid;
    }
    int ans;
    if (judge(R, slen))
        ans = R;
    else
        ans = L;
    if (ans < 4)
        printf("0");
    else
        printf("%d", ans + 1);
    return 0;
}

乐曲主题Musical Themes的更多相关文章

  1. 洛谷P2743 乐曲主题Musical Themes [USACO5.1] SA

    正解:SA 解题报告: 传送门 这题三个条件嘛,那就一个个考虑下都解决了就把这题解决了嘛QwQ 那就直接分别针对三个条件写下各个击破就欧克辣? 1)长度大于等于5:求出答案之后和5比大小 2)不能有公 ...

  2. Luogu P2743 [USACO5.1]乐曲主题Musical Themes

    链接 \(Click\) \(Here\) 人生第一道后缀数组的题目.首先要对输入的串进行差分处理,差分后长度为(\(n - 1\))的相同子段就是原串中长度为\(n\)的相同(可变调)子段.求出来\ ...

  3. [USACO5.1] 乐曲主题Musical Themes

    题目链接:戳我 Emmm......hash怎么做啊不会啊 这里是SA后缀数组版本的 就是先两两做差分,作为要处理后缀的数组.普通地求出来h数组之后,我们二分这个答案,然后判定是否合法就行了.是否合法 ...

  4. P2743(poj1743) Musical Themes[差分+后缀数组]

    P2743 乐曲主题Musical Themes(poj1743) 然后呢这题思路其实还是蛮简单的,只是细节特别多比较恶心,忘记了差分带来的若干疏漏.因为转调的话要保证找到相同主题,只要保证一段内相对 ...

  5. [转]jQuery EasyUI 扩展-- 主题(Themes)

    主题(Themes)允许您改变站点的外观和感观.使用主题可以节省设计的时间,让您腾出更多的时间进行开发.您也可以创建一个已有主题的子主题. 主题生成器(Theme Builder) jQuery UI ...

  6. USACO Section 5.1 Musical Themes(枚举)

    直接枚举O(n^3)会TLE,只要稍微加点优化,在不可能得到更优解时及时退出.其实就是道水题,虽说我提交了6次才过= =..我还太弱了 -------------------------------- ...

  7. USACO 5.1 Musical Themes(哈希+二分)

    Musical ThemesBrian Dean A musical melody is represented as a sequence of N (1 <= N <= 5000) n ...

  8. Android应用开发中的风格和主题(style,themes)

    http://www.cnblogs.com/playing/archive/2011/04/01/2002469.html 越来越多互联网企业都在Android平台上部署其客户端,为了提升用户体验, ...

  9. [USACO 5.1.3]乐曲主题

    Description 我们用N(1 <= N <=5000)个音符的序列来表示一首乐曲,每个音符都是1..88范围内的整数,每个数表示钢琴上的一个键.很不幸这种表示旋律的方法忽略了音符的 ...

随机推荐

  1. 【CSS】使用CSS控制文字过多自动省略号

    使用CSS可以设置一下样式: <style> u,small{ overflow: hidden; text-overflow: ellipsis; display: -webkit-bo ...

  2. 26个高效工作的小技巧 z

    1.时间常有,时间优先. 2.时间总会有的:每天只计划4-5 小时真正的工作. 3.当你在状态时,就多干点:不然就好好休息:有时候会连着几天不是工作状态,有时在工作状态时却又能天天忙活 12 小时,这 ...

  3. Seinfeld(杭电3351)

    Seinfeld Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total S ...

  4. powerDesignner连接数据库

    http://hi.baidu.com/huntererpang/item/e65e1c48aa0ab50a6dc2f090 选用microsoft odbc for oracle 数据源名称:我喜欢 ...

  5. Android创建和使用数据库

    一.关系型数据库SQLIte         每一个应用程序都要使用数据.Android应用程序也不例外,Android使用开源的.与操作系统无关的SQL数据库-SQLite. SQLite第一个Al ...

  6. angular 指令封装弹出框效果

    就直接用bs的警告框啦~,Duang~ 功能 可以设置message和type,type就是bs内置的几种颜色 默认提示3秒框自动关闭,或者点击x号关闭 代码 模板 <div class=&qu ...

  7. Caffe学习系列(12):训练和测试自己的图片--linux平台

    Caffe学习系列(12):训练和测试自己的图片   学习caffe的目的,不是简单的做几个练习,最终还是要用到自己的实际项目或科研中.因此,本文介绍一下,从自己的原始图片到lmdb数据,再到训练和测 ...

  8. cubietruck制作刷新lubuntu-kernel

    一:安装交叉编译工具链以及相应的工具(系统最好是ubutnu-64位-server) sudo apt-get install g++ sudo apt-get install libncurses5 ...

  9. 在html文件引入其它html文件的几种方法

    1.IFrame引入,看看下面的代码 <IFRAME NAME="content_frame" width=100% height=600 marginwidth=0 mar ...

  10. VMware Workstation 14创建mac-10.12虚拟机详细步骤

     一.VMware和unlocker的下载和安装 链接:https://pan.baidu.com/s/15Z4DqRENt6JdyfJef_VWSw 密码:40vw 1.安装VMware Works ...