zoukankan      html  css  js  c++  java
  • poj1743

    题意:给出一段只有音高(整数表示),没有节奏的乐谱,问其中最长的曲调相同的没有重叠的两段的长度是多少。

    分析:后缀数组,一定要注意,吉大的模板的nlogn算法,要初始化n=strlen(s) +1,另外,s,sa,rank一定要从0位置开始使用。height从1位置开始有意义。

    这题是要在求出相邻音高之差之后找不重叠(无公共部分)的最长的重复出现过至少两次的串,也就是在height数组中找到一个连续段,其各项均大于d且sa数组中的对应段中最大值最小值之差要大于d。找到最大的d即可。d符合一个性质,就是小的d都满足,大的d都不满足。用二分法找分界线即可。

    View Code
    #include <iostream>
    #include
    <cstdio>
    #include
    <cstdlib>
    #include
    <cstring>
    usingnamespace std;

    #define N 20004

    int s[N], f[N];
    int n, sa[N], height[N], rank[N], tmp[N], top[N];

    void makesa()
    {
    int i, j, len, na;
    na
    = (n <256?256 : n);
    memset(top,
    0, na *sizeof(int));
    for (i =0; i < n; i++)
    top[rank[i]
    = s[i] &0xff]++;
    for (i =1; i < na; i++)
    top[i]
    += top[i -1];
    for (i =0; i < n; i++)
    sa[
    --top[rank[i]]] = i;
    for (len =1; len < n; len <<=1)
    {
    for (i =0; i < n; i++)
    {
    j
    = sa[i] - len;
    if (j <0)
    j
    += n;
    tmp[top[rank[j]]
    ++] = j;
    }
    sa[tmp[top[
    0] =0]] = j =0;
    for (i =1; i < n; i++)
    {
    if (rank[tmp[i]] != rank[tmp[i -1]] || rank[tmp[i] + len]
    != rank[tmp[i -1] + len])
    top[
    ++j] = i;
    sa[tmp[i]]
    = j;
    }
    memcpy(rank, sa, n
    *sizeof(int));
    memcpy(sa, tmp, n
    *sizeof(int));
    if (j >= n -1)
    break;
    }
    }

    void lcp()
    {
    int i, j, k;
    for (j = rank[height[i = k =0] =0]; i < n -1; i++, k++)
    while (k >=0&& s[i] != s[sa[j -1] + k])
    height[j]
    = (k--), j = rank[sa[j] +1];
    }

    bool ok(int d)
    {
    int l = sa[0], r = sa[0];
    for (int i =0; i < n; i++)
    {
    if (height[i] < d)
    {
    l
    = sa[i];
    r
    = sa[i];
    continue;
    }
    if (sa[i] < l)
    l
    = sa[i];
    if (sa[i] > r)
    r
    = sa[i];
    if (r - l > d)
    returntrue;
    }
    returnfalse;
    }

    int binarysearch()
    {
    int l =0;
    int r = n;
    while (l < r)
    {
    int mid = (l + r) /2+ ((l + r) &1);
    if (ok(mid))
    l
    = mid;
    else
    r
    = mid -1;
    }
    return l;
    }

    int main()
    {
    //freopen("t.txt", "r", stdin);
    while (scanf("%d", &n), n)
    {
    for (int i =0; i < n; i++)
    scanf(
    "%d", &f[i]);
    for (int i =0; i < n -1; i++)
    s[i]
    = f[i +1] - f[i];
    makesa();
    lcp();
    int ans = binarysearch();
    if (ans >=4)
    printf(
    "%d\n", ans +1);
    else
    printf(
    "0\n");
    }
    return0;
    }
  • 相关阅读:
    Unity错误提示大全(遇到问题就更新)
    使用log4Net输出调试信息
    3.创建Manager类,演示对TestUser进行增删改查功能
    2.创建NHibernateHelper帮助类,生成sessionFactory
    1.使用FluentNHibemate 操作数据库,添加映射到数据库
    MySql介绍与安装
    搭建unity客户端
    搭建服务器端
    Photon介绍与安装
    简练软考知识点整理-实施定量风险分析
  • 原文地址:https://www.cnblogs.com/rainydays/p/2080914.html
Copyright © 2011-2022 走看看