ranoj p090 未出现的子串

题目:未出现的子串 

题目描述

[说明]此题中的子数字串,数字并不一定连续出现在母数字串中.比如我们定义1 3 是串1 5 3
的一个子串,3 5 不是1 5 3 的一个子串.
1 5 3 的所有子串为:
1
5
3
1 5
5 3
1 3
1 5 3
.
[题目描述]有一个长度为的数字串,其中会出现数字1,2,3,...,q(5<=q<=9).SubRaY 遇到的问
题是,需要求出一个长度最小的串(出现的数字也是1..q),使得该串不是这个数字串的子串.
了简化问题,你只需要输出这个串的长度即可.
例如对于数字串S=
1 3 5 2 4 1 3 5 2 2 2 2 3 4 1 5 3 2(q=5)
长度为的数字子串全出现过,但是你找不出子串S'=4 4 4.因此答案是3
[数据范围]
对于30%的数据,1<=n<=20,q=5
对于100%的数据,1<=n<=100000,5<=q<=9

输入格式

第一行两个数,串长和出现的数字的个数q
接下来行表示该数字串每一位的数字.

输出格式

未出现的子串的最小长度

样例输入

18 5

1

3

5

2

4

1

3

5

2

2

2

2

3

4

1

5

3

2

样例输出

 3

 

注:这道题目可以有两种解法。第一种是DP:我们首先定义匹配的定义:一个合法的子串,对于每一个数字,如果后面从1-q每一个数字都能成功做到不少于长度为k的匹配,那么这个数字的成功匹配长度就是k+1,于是有了状态转移方程:f[i]=min{f[k]}+1; (i ∈[1..q],k>i)。由于是寻找后面的匹配长度,所以要进行倒推;第二种方法是数学中的集合思想,我们将这个数字序列分成k份,保证每一份中含有1..q并且最多分成k份,那么最后的答案就是k+1。

代码1:
var

  a:array[0..100000] of longint;

  f:array[0..9] of longint;

  i,j,k,ans,n,q:longint;



function min(x,y:longint):longint;

begin

  if x<y then exit(x);

  exit(y);

end;



function max(x,y:longint):longint;

begin

  if x>y then exit(x);

  exit(y);

end;



begin

  readln(n,q);

  for i:=1 to n do readln(a[i]);

  ans:=0;

  for i:=n downto 1 do

    begin

      k:=maxlongint;

      for j:=1 to q do

        k:=min(k,f[j]);

      f[a[i]]:=k+1;

    end;

  for i:=1 to q do

    ans:=max(ans,f[i]);

  writeln(ans);

end.

代码2:
var

  i,j,k,ans,n,m,q:longint;

  vv:boolean;

  v:array[0..10] of boolean;

begin

  readln(n,q);

  ans:=1;

  fillchar(v,sizeof(v),false);

  for i:=1 to n do

    begin

      vv:=true;

      for j:=1 to q do

        if not v[j] then

          begin

            vv:=false;

            break;

          end;

      if vv then

        begin

          fillchar(v,sizeof(v),false);

          inc(ans);

        end;

      readln(k);

      v[k]:=true;

    end;

  writeln(ans);

end.

你可能感兴趣的:(OJ)