POJ1743

题目意思是求不重叠的最长相同变化的子串,输出该长度

比如1 2 3 4 5 6 7 8 9 10,最长长度为5,因为子串1 2 3 4 5 和 6 7 8 9 10变化都一样的

思路:既然要求变化一样,那么可以让原数组前后相减,然后利用后缀数组height的性质求子串最长公共前缀即可

height性质:1.height[i]表示排名为i和i-1的子串的最长公共前缀

PS:预处理数组时要留意,把n个数删去第一个 当作n-1个数来求重复子串 (间隔至少为1)然后最长重复子串长度+1就是所求答案

当然小于5时输出0

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<string.h>
#define clear(x) memset(x,0,sizeof(x))
using namespace std; const int MAXN=400000+100;
int count[MAXN];
void radix(int *str,int *a,int *b,int n,int m)
{ clear (count);
for(int i=0;i<n;++i)++count[str[a[i]]];
for(int i=1;i<=m;++i)count[i]+=count[i-1];
for(int i=n-1;i>=0;--i)b[--count[str[a[i]]]]=a[i];
}
int rank[MAXN],a[MAXN],b[MAXN];
void sorted_suffix_array(int *str,int *sa,int n,int m)
{ clear (rank);clear(a);clear(b);
for(int i=0;i<n;++i)rank[i]=i;
radix(str,rank,sa,n,m); rank[sa[0]]=0;
for(int i=1;i<n;++i)rank[sa[i]]=rank[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]);
for(int i=0;(1<<i) <n;++i)
{
for(int j=0;j<n;++j)
{
a[j]=rank[j]+1;
b[j]=j+(1<<i)>=n? 0:rank[j+(1<<i)]+1;
sa[j]=j;
}
radix(b,sa,rank,n,n);
radix(a,rank,sa,n,n);
rank[sa[0]]=0;
for(int j=1;j<n;++j)
{
rank[sa[j]]=rank[sa[j-1]]+(a[sa[j-1]]!=a[sa[j]]||b[sa[j-1]]!=b[sa[j]]);
}
}
} int Rank[MAXN];
void calc_height(int *str,int *sa,int *h,int n)
{ clear(Rank);
int k=0;
h[0]=0;
for(int i=0;i<n;++i)Rank[sa[i]]=i;
for(int i=0;i<n;++i)
{
k= k==0?0:k-1;
if(Rank[i]!=0)
while(str[i+k]==str[sa[Rank[i]-1]+k])++k;
h[Rank[i]]=k;
}
} int s[MAXN],sa[MAXN],h[MAXN],duprank[MAXN];
string duplicate_substr(string str,bool is_joint)
{
string rev; clear (s);clear(sa);clear(h);clear(duprank);
int n=str.length();
copy(str.begin(),str.end(),s);
for(int i=0;i<n-1;i++)
s[i]=s[i+1]-s[i]+100;
n--;
sorted_suffix_array(s,sa,n,500);
calc_height(s,sa,h,n);
int ans1=0,pos1=0;
for(int i=0;i<n;i++)
duprank[sa[i]]=i;
for(int i=0;i<n;i++)
{
if(h[duprank[i]]>ans1){ans1=h[duprank[i]];pos1=i;}
}
if(is_joint)return str.substr(pos1,ans1); int low=0,high=n-1;
int ans2=0,pos21=0,pos22=0;
while(low<=high)
{
int mid=(low+high)/2;
bool ok=false;
for(int i=0;i<n;)
{
int j=i+1,minPos=sa[i],maxPos=sa[i];
while(j<n&&h[j]>=mid)
{
minPos=min(minPos,sa[j]);
maxPos=max(maxPos,sa[j]);
j++;
}
if((maxPos-minPos)>mid)
{
ok=true;
if(mid>ans2)
{
ans2=mid;
pos21=minPos;
pos22=maxPos;
}
break;
}
i=j;
}
if(ok){low=mid+1;}
else{high=mid-1;}
}
if(!is_joint)return str.substr(pos21,ans2);
} int num[MAXN];
int main()
{freopen("t.txt","r",stdin);
int n;
while(scanf("%d",&n))
{
string a;
if(n==0)return 0;
for(int i=0;i<n;i++)
{
scanf("%d",&num[i]);
} for(int i=0;i<n;i++)
{
char cc[2];
cc[0]=num[i];cc[1]=0;
a.append(cc);
}
int ans=duplicate_substr(a,false).length()+1;
if(ans>=5)printf("%d\n",ans);
else printf("0\n");
}
return 0;
}

  楼教主的题目 厉害

POJ1743 Musical Theme 最长重复子串 利用后缀数组的更多相关文章

  1. POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)+后缀数组模板

    Milk Patterns Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 7586   Accepted: 3448 Cas ...

  2. POJ 3261 可重叠的 k 次最长重复子串【后缀数组】

    这也是一道例题 给定一个字符串,求至少出现 k 次的最长重复子串,这 k 个子串可以重叠.算法分析:这题的做法和上一题差不多,也是先二分答案,然后将后缀分成若干组.不同的是,这里要判断的是有没有一个组 ...

  3. POJ-1743 Musical Theme(最长不可重叠子串,后缀数组+二分)

    A musical melody is represented as a sequence of N (1<=N<=20000)notes that are integers in the ...

  4. POJ 3294 Life Forms [最长公共子串加强版 后缀数组 && 二分]

    题目:http://poj.org/problem?id=3294 Life Forms Time Limit: 5000MS   Memory Limit: 65536K Total Submiss ...

  5. 【poj1226-出现或反转后出现在每个串的最长公共子串】后缀数组

    题意:求n个串的最长公共子串,子串出现在一个串中可以是它的反转串出现.总长<=10^4. 题解: 对于每个串,把反转串也连进去.二分长度,分组,判断每个组. #include<cstdio ...

  6. 【poj3693-重复次数最多的连续重复子串】后缀数组

    题意:给定一个串,长度<=10^5,求它重复次数最多的连续重复子串(输出字典序最小的那个). 例如ccabcabc,答案就是abcabc 一开始没想清楚,结果调了好久. 原理: 按照L划分,因为 ...

  7. cogs249 最长公共子串(后缀数组 二分答案

    http://cogs.pro:8080/cogs/problem/problem.php?pid=pxXNxQVqP 题意:给m个单词,让求最长公共子串的长度. 思路:先把所有单词合并成一个串(假设 ...

  8. 【poj3294-不小于k个字符串中最长公共子串】后缀数组

    1.注意每两个串之间的连接符要不一样. 2.分组的时候要注意最后一组啊!又漏了! 3.开数组要考虑连接符的数量.100010是不够的至少要101000. #include<cstdio> ...

  9. POJ1743 Musical Theme —— 后缀数组 重复出现且不重叠的最长子串

    题目链接:https://vjudge.net/problem/POJ-1743 Musical Theme Time Limit: 1000MS   Memory Limit: 30000K Tot ...

随机推荐

  1. Spider-Python爬虫之使用Selenium模拟浏览器行为

    分析 他的代码比较简单,主要有以下的步骤:使用BeautifulSoup库,打开百度贴吧的首页地址,再解析得到id为new_list标签底下的img标签,最后将img标签的图片保存下来. header ...

  2. 洛谷 3953 NOIP2017提高组Day1 T3 逛公园

    [题解] 先建反向图,用dijkstra跑出每个点到n的最短距离dis[i] 设f[u][k]表示dis(u,n)<=mindis(u,n)+k的方案数.对于边e(u,v,w),走了这条边的话需 ...

  3. ELK搭建过程中出现的问题与解决方法汇总

    搭建过程中出现的问题 elasticsearch启动过程中报错[1] ERROR: [1] bootstrap checks failed [1]: the default discovery set ...

  4. 第一个web项目

    1)       创建Java Web Project 2)       创建相应的包 3)       创建类并继承于HttpServlet 4)       重写service()方法 5)    ...

  5. SPOJ 3261 (树套树傻逼题)

    As another one of their crazy antics, the N (1 ≤ N ≤ 100,000) cows want Farmer John to race against ...

  6. 变量&字符串

    变量 变量定义规范: # 声明变量: name = "Neo Zheng" # name为变量名(标识符),"Neo Zheng"是变量值. 变量定义规则: 1 ...

  7. 2017 CCPC 杭州 HDU6273J 区间修改(线段树&差分数组)

    http://acm.hdu.edu.cn/downloads/CCPC2018-Hangzhou-ProblemSet.pdf 解析 线段树区间延迟更新 或 差分数组 两个数   统计2和3的最少的 ...

  8. Java日期LocalDate使用

    在做报表统计时,需要对指定时间内的数据做统计,则需要使用到时间日期API 在此使用的是java.util.Date的完美私生子LocalDate类 LocalDate方法介绍 now() : 从默认时 ...

  9. Ubuntu 16.04在搭建Redis Cluster搭建时,使用gem install redis时出现:ERROR: While executing gem ... (Gem::FilePermissionError) You don't have write permissions for the /var/lib/gems/2.3.0 directory.

    注意:千万不要使用sudo来执行gem install redis. 解决方法: sudo apt-get update sudo apt-get install git-core curl zlib ...

  10. Oracle建表提示SQL 错误: ORA-00904: : 标识符无效

    Oracle建表提示: 错误报告:SQL 错误: ORA-00904: : 标识符无效00904. 00000 -  "%s: invalid identifier"*Cause: ...