题目:未出现的子串
题目描述
[说明]此题中的子数字串,数字并不一定连续出现在母数字串中.比如我们定义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
共7 个.
[题目描述]有一个长度为n 的数字串,其中会出现数字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)
长度为1 和2 的数字子串全出现过,但是你找不出子串S'=4 4 4.因此答案是3
[数据范围]
对于30%的数据,1<=n<=20,q=5
对于100%的数据,1<=n<=100000,5<=q<=9
输入格式
第一行两个数,串长n 和出现的数字的个数q
接下来n 行表示该数字串每一位的数字.
输出格式
未出现的子串的最小长度
样例输入
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.