后缀数组求最长重复且不重叠子串。

poj 1743 传送门

洛谷 P2743 传送门

1.子串可以“变调”(即1 3 6和3 5 8视作相同)。解决办法:求字符串相邻元素的差形成新串。用新字符串求解最长重复子串即可。

2.最长重复子串不能重叠。解决办法:用sa数组判断开始位置。

倍增答案即可,从1到n枚举height,记录子串开始的最左端、最右端。

如果找到了两个后缀,其公共前缀长度大于k,且其开始位置之间的间隔大于k,就满足条件。

由height数组的性质可得:要使x、y的公共前缀长度大于k,则需要h[x+1]、h[x+2]......h[y]全部大于k。

所以只要有一个没有大于k,就得重新开始。即:重置子串开始的最左端、最右端。

最后答案需要+1,并判断是否大于等于5(题意要求)。

注意poj的数据范围比洛谷上大,而且有多组测试数据。

下面只给出poj1743的代码。

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; int n,ans;
int s[];
int sa[],rk[];
int tr[],h[]; int cmp(int x,int y,int k)
{
if(x+k>n||y+k>n)return ;
return rk[x]==rk[y]&&rk[x+k]==rk[y+k];
} void cal()
{
int i,cnt;
for(i=;i<=n;i++)h[s[i]]++;
for(cnt=,i=;i<=;i++)if(h[i])tr[i]=++cnt;
for(i=;i<=;i++)h[i]+=h[i-];
for(i=;i<=n;i++)rk[i]=tr[s[i]],sa[h[s[i]]--]=i;
for(int k=;cnt!=n;k<<=)
{
for(i=;i<=n;i++)h[i]=;
for(i=;i<=n;i++)h[rk[i]]++;
for(i=;i<=n;i++)h[i]+=h[i-];
for(i=n;i;i--)if(sa[i]>k)tr[sa[i]-k]=h[rk[sa[i]-k]]--;
for(i=;i<=k;i++)tr[n-i+]=h[rk[n-i+]]--;
for(i=;i<=n;i++)sa[tr[i]]=i;
for(cnt=,i=;i<=n;i++)tr[sa[i]]=cmp(sa[i],sa[i-],k)?cnt:++cnt;
for(i=;i<=n;i++)rk[i]=tr[i];
}
for(i=;i<=n;i++)h[i]=;
for(i=;i<=n;i++)
{
if(rk[i]==)continue;
for(int j=max(,h[rk[i-]]-);;j++)
{
if(s[i+j-]==s[sa[rk[i]-]+j-])h[rk[i]]=j;
else break;
}
}
} int check(int k)
{
if(k>n)return ;
int l,r;
l=r=sa[];
for(int i=;i<=n;i++)
{
if(h[i]>=k)
{
l=min(l,sa[i]);
r=max(r,sa[i]);
if(r-l>k)return ;
}else l=r=sa[i];
}
return ;
} int main()
{
scanf("%d",&n);
while(n)
{
memset(h,,sizeof(h));
memset(tr,,sizeof(tr));
memset(rk,,sizeof(rk));
memset(sa,,sizeof(sa));
ans=;
for(int i=;i<=n;i++)scanf("%d",&s[i]);
for(int i=;i<n;i++)s[i]=s[i+]-s[i]+;
cal();
for(int i=;i>=;i--)
if(check(ans|(<<i)))ans|=(<<i);
ans=(ans+)>=?(ans+):;
printf("%d\n",ans);
scanf("%d",&n);
}
return ;
}

[USACO5.1] Musical Themes的更多相关文章

  1. USACO Section 5.1 Musical Themes(枚举)

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

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

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

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

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

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

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

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

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

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

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

  7. 乐曲主题Musical Themes

    SA例题 题面 对于串 \(S\) 的两个子串 \(A\) 和 \(B\) ,满足 \(k = |A| = |B|\),\(\exists c \forall i\, a_i + c=b_i\),且 ...

  8. POJ 1743 [USACO5.1] Musical Theme (后缀数组+二分)

    洛谷P2743传送门 题目大意:给你一个序列,求其中最长的一对相似等长子串 一对合法的相似子串被定义为: 1.任意一个子串长度都大于等于5 2.不能有重叠部分 3.其中一个子串可以在全部+/-某个值后 ...

  9. 学校作业-Usaco DP水题

    好吧,因为USACO挂掉了,所以我写的所有代码都不保证正确性[好的,这么简单的题,再不写对,你就可以滚粗了! 第一题是USACO 2.2.2 ★Subset Sums 集合  对于从 1 到 N 的连 ...

随机推荐

  1. Jupyter notebook 和 Jupyter lab 的区别

    Jupyter Notebook Jupyter Notebook 是一个款以网页为基础的交互计算环境,可以创建Jupyter的文档,支持多种语言,包括Python, Julia, R等等.广泛用于数 ...

  2. shell并行处理

    for i in (file1 file2 file3), do process_a $i | tee process_a $i_a.txt | process_b > $i_b.txt &am ...

  3. RSAUtils加密解密

    import org.apache.commons.codec.binary.Base64; import org.apache.commons.io.IOUtils; import javax.cr ...

  4. 前端-HTLM

    前端简介: 什么是前端? 任何与用户直接打交道的操作界面都可以被称为前端,如:网页界面,手机界面.... 前端的学习历程和内容: 要学习的内容: 三大重点: 1.Web服务的本质: 浏览器中敲入网址回 ...

  5. grep -v|grep -F

    cat a cat b #取b中不含1的行 b #b先和a比较,两者交集与b再取交集 b: b: b: b: b: b:22 $ grep -F a -f a b#a先和a比较,两者交集与b再取交集 ...

  6. ZJNU 1153 - 找单词——中级

    状态转移b[i]记录价值为i的单词种类数d[j+k*i]+=b[j] , k<=a[i]&&j+k*i<=50表示价值为j+k*i的单词可以由价值为j的单词加上k个i字母转 ...

  7. HEX 文件格式

    例 FDFFF885C3 :每行开头 第一个字节:表示本行的数据长度, 第二个,第三个字节表示本行数据的起始地址. 第四字节表示数据类型,数据类型有:0x00.0x01.0x02.0x03.0x04. ...

  8. Codeforces Round #598 (Div. 3)E(dp路径转移)

    题:https://codeforces.com/contest/1256/problem/E 题意:给一些值,代表队员的能力值,每组要分3个或3个以上的人,然后有个评价值x=(队里最大值-最小值), ...

  9. Git ubuntu 升级

    外文文档 This team will distribute the most current stable package of Git for Ubuntu. Stable releases: h ...

  10. okhttp 拦截问题

    builder.addInterceptor(chain -> { Request request = chain.request(); Response response = chain.pr ...