poj 1743 Musical Theme(后缀数组)

这篇博客主要介绍了如何解决POJ 1743 'Musical Theme'问题,重点在于理解后缀数组的概念。作者在尝试过程中遇到多次错误,最终从讨论区找到正确解决方案。关键点在于处理转置操作,通过先做差再求height数组的方法来确保差值不变。解题思路参考了《算法合集之《后缀数组——处理字符串的有力工具》》一文。
摘要由CSDN通过智能技术生成

后缀数组第一题,RE好多次,看了好多题解,最终在discuss里找到了正解:http://poj.org/showmessage?message_id=341423
代码里是先做差再求height数组,原因是题目中的转置,两个数字都加上一个相同的量,两个数字之间的差值也是不会变的。
题目的思路是看的:算法合集之《后缀数组——处理字符串的有力工具》这里面的,这个是里面的例题。。。

#include <cstdio>
#include <cstring>
#include <algorithm>

const int MAXN = 20010;
int N;
int r[MAXN],sa[MAXN];
int wa[MAXN],wb[MAXN],wv[MAXN],ws[MAXN];

int cmp(int *r,int a,int b,int l)
{
    return r[a]==r[b]&&r[a+l]==r[b+l];
}

void da(int *r, int *sa, int n, int m)
{
    int i,j,p,*x=wa,*y=wb,*t;
    for(i=0; i<m; i++) ws[i]=0;
    for(i=0; i<n; i++) ws[x[i]=r[i]]++;
    for(i=1; i<m; i++) ws[i]+=ws[i-1];
    for(i=n-1; i>=0; i--) sa[--ws[x[i]]]=i;
    for(j=1,p=1; p<n; j*=2,m=p)
    {
        for(p=0,i=n-j; i<n; i++) y[p++]=i;
        for(i=0; i<n; i++) if(sa[i]>=j) y[p++]=sa[i]-j;
        for(i=0; i<n; i++) wv[i]=x[y[i]];
        for(i=0; i<m; i++) ws[i]=0;
        for(i=0; i<n; i++) ws[wv[i]]++;
        for(i=1; i<m; i++) ws[i]+=ws[i-1];
        for(i=n-1; i>=0; i--) sa[--ws[wv[i]]]=y[i];
        for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1; i<n; i++)
            x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
    }
    return;
}

int rank[MAXN],height[MAXN];
void calheight(int *r, int *sa, int n)
{
    int i,j,k=0;
    for(i=1; i<=n; i++) rank[sa[i]]=i;
    for(i=0; i<n; height[rank[i++]]=k)
        for(k?k--:0,j=sa[rank[i]-1]; r[i+k]==r[j+k]; k++);
    return;
}

bool C(int d)
{
    int minn = MAXN;
    int maxn = -1;
    for(int i = 1; i <= N; ++i)
    {
        if(height[i] > d)
        {
            maxn = std::max(maxn,std::max(sa[i],sa[i-1]));
            minn = std::min(minn,std::min(sa[i],sa[i-1]));
            if(maxn - minn > d) return true;
        }
    }
    return false;
}

void solve()
{
    int lb = 4,ub = N/2;
    while(lb < ub)
    {
        int mid = (lb+ub)/2;
        if(C(mid)) lb = mid+1;
        else ub = mid;
    }
    printf("%d\n",lb < 4 ? 0:lb+1);
}

int main()
{
    while(scanf("%d",&N) && N)
    {
        int pre,note;
        scanf("%d",&pre);
        for(int i = 0; i < N-1; ++i)
        {
            scanf("%d",&note);
            r[i] = note - pre+100;
            pre = note;
        }
        if(N < 10)
        {
            printf("0\n");
            continue;
        }
        r[N-1] = 0;
        da(r,sa,N,200);
        calheight(r,sa,N-1);
        solve();
    }
    return 0;
}
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。、可私 6信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 、可私信6博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值