1、 诗歌的主题(chinese)
问题描述
众所舟舟知,zsz童鞋是语文课代表,此人ws至极,仗着职权之便,从来不交语文积累本,终于有一天,他被老班发现了(乌卡卡卡卡卡)。于是老班给他出了一个特别的诗歌鉴赏题:
为了方便描述,我们将诗歌中的字用数字代表,现在zsz要找出诗歌中长度最长的一个主题。
诗歌的主题要满足以下几个要求:
1、 它是整首诗歌的一个字串
2、 长度至少为5
3、 在诗歌中必须重复出现(可能经过诗人的加工,加工方法见下文)
4、 重复出现的同一主题不能有公共部分
加工的意思是主题序列中的每个数字,都被加上或减去了同一个整数。给定一首诗歌,计算其中最长的主题长度。
输入格式
第一行一个整数n,表示诗歌的长度
下面的每一行包含20个整数,表示诗歌的内容,最后一行的数的个数可能小于n,总之,一共n个整数。
输出格式
一个整数,即最长的主题长度。如果找不到符合要求的主题,输出0
样例输入
30
25 27 30 34 39 45 52 60 69 79 69 60 52 45 39 34 30 26 22 18
82 78 74 70 66 67 64 60 65 80
样例输出
5
数据范围
1<=n<=5000
1<=ai(每个数字)<=100
Liukeke 的学科试题之四·语文。
首先,我们将相邻的两项对减,也就是求出它的每两项的差来,这样就相当于把那个“加工”去掉了。----------------我考试的时候就是因为这个 WA 的,%>_<%
然后就好办了,枚举+二分,水过。
不过要注意,这样求出来的长度是这个序列的“差”数,也就是间隔数,需要 +1 。
代码(SueMiller)
program ACRush;
var a,b:array[0..5001]of integer;
i,j,k,n:integer;
ans:integer;
l,r,m:integer;
function same(x,y,q:integer):boolean;
var i:integer;
begin
for i:=1 to q do
if b[x-1+i]<>b[y-1+i] then exit(false);
exit(true);
end;
function check(x:integer):boolean;
var i,j:integer;
begin
for i:=n-x-x+1 downto 1 do
for j:=i+x to n-x+1 do
if same(i,j,x) then exit(true);
exit(false);
end;
begin
assign(input,'chinese.in');reset(input);
assign(output,'chinese.out');rewrite(output);
readln(n);
read(a[0]);
for i:=1 to n-1 do
begin
read(a[i]);
b[i]:=a[i]-a[i-1];
end;
dec(n);
l:=5;
r:=n>>1;
m:=(l+r)>>1;
while r-l>2 do
begin
if check(m) then
begin
l:=m;
m:=(l+r)>>1;
end
else begin
r:=m;
m:=(l+r)>>1;
end;
end;
if check(r) then writeln(r+1)
else
if check(m) then writeln(m+1)
else if check(l) then writeln(l+1)
Else writeln(0);
close(input);close(output);
End.
然后,还有一种比较好的枚举:枚举 l ,然后直接判断间隔为 l 的两个数字是否相同,相同的话记录的长度加一,不同的话更新 ans 。
其实这个方法我也不太明白。。。。。。。。。
代码(Liukeke)
program liukeke;
var
a,b:array[0..5001] of longint;
i,n,ans,num,l:longint;
begin
assign(input,'chinese.in');reset(input);
assign(output,'chinese.out');rewrite(output);
readln(n);
for i:=1 to n do
read(a[i]);
for i:=1 to n-1 do
b[i]:=a[i+1]-a[i];
ans:=0;
num:=1;
dec(n);
for l:=5 to n-1 do
begin
if num>ans then ans:=num;
num:=1;
for i:=1 to n-l do
if (b[i]=b[i+l])and(num+1<=l) then
inc(num)
else
begin
if num>ans then ans:=num;
num:=1;
end;
end;
if ans>=5 then
writeln(ans)
else writeln(0);
close(input);
close(output);
end.