题意:给出 n (n ≤15 ) 个字符串,求一个最短的串 S ,使得给出的那些串都是 S 的子
串。如果有多个解输出字典序最小的一个。
这题写的我快哭出来了55555555555
先说一下我写这道题的经历吧。一开始很容易就想到用f[i,j]表示状态i以j结尾时的最短长度,然后我用了一个f1数组来记录字符串,然后发现MLE……接着便把f1数组去掉,但冥思苦想都想不到一种优美的方法来找答案。弱渣的BPM表示可以用dp来搞,但我感觉太麻烦,于是BPM又告诉我说可以把f[i,j]改为状态为i且j为开头时的最短长度,这样可以贪心结果并维护字典序,然后我便改了……结果发现不管怎么搞都是WA……最后仍是BPM告诉我,若某一个字符串是另一个的子串,则要把该串去掉,不然就会WA……
最后AC出来的那一刻,感觉整个人生都圆满了!!!
突然想起题解已经全在上面了。
代码:
var t,l,i,j,k,a1,x,last,n,ans,m:longint; w:array[0..15] of longint; s:array[0..15] of ansistring; len,a,b:array[0..15] of longint; g:array[0..15,0..15] of longint; f:array[0..60000,1..15] of longint; anss:ansistring; function min(x,y:longint):longint; begin if x<y then exit(x) else exit(y); end; procedure sort; var i,j:longint; begin for i:=1 to n-1 do for j:=i+1 to n do if s[i]>s[j] then begin s[0]:=s[i];s[i]:=s[j];s[j]:=s[0]; len[0]:=len[i];len[i]:=len[j];len[j]:=len[0]; end; end; function work(x:longint):longint; begin work:=0; while x>0 do begin inc(work); x:=x div 2; end; end; procedure dfs(x,d:longint); var u:longint; i,min:longint; mins:ansistring; begin if x=0 then exit; mins:=''; for i:=1 to n do if f[x,i]-g[w[d-1],i]=ans then begin if (mins='')or(anss+copy(s[i],g[w[d-1],i]+1,len[i]-g[w[d-1],i])<mins) then begin mins:=anss+copy(s[i],g[w[d-1],i]+1,len[i]-g[w[d-1],i]); u:=i; end; end; w[d]:=u; anss:=mins; ans:=ans-len[u]+g[w[d-1],u]; dfs(x-(1 shl (u-1)),d+1); end; procedure sort1; var i,j:longint; begin for i:=1 to n-1 do for j:=i+1 to n do if len[i]>len[j] then begin s[0]:=s[i];s[i]:=s[j];s[j]:=s[0]; len[0]:=len[i];len[i]:=len[j];len[j]:=len[0]; end; end; begin readln(t); for l:=1 to t do begin readln(n); for i:=1 to n do begin readln(s[i]); len[i]:=length(s[i]); end; sort1; m:=0; for i:=1 to n-1 do for j:=i+1 to n do for k:=1 to len[j]-len[i]+1 do if copy(s[j],k,len[i])=s[i] then begin s[i]:='Z'+s[i]; inc(m); break; end; sort; n:=n-m; fillchar(g,sizeof(g),0); for i:=1 to n do for j:=1 to n do if i<>j then for k:=min(len[i],len[j]) downto 1 do if copy(s[i],len[i]-k+1,k)=copy(s[j],1,k) then begin g[i,j]:=k; break; end; fillchar(f,sizeof(f),$7f div 3); for i:=1 to n do f[1 shl (i-1),i]:=len[i]; for i:=1 to 1 shl n-1 do begin x:=i; a1:=0; while x>0 do begin inc(a1); a[a1]:=x and -x; x:=x-x and -x; b[a1]:=work(a[a1]); end; for j:=1 to a1 do for k:=1 to a1 do if j<>k then if f[i-a[j],b[k]]-g[b[j],b[k]]+len[b[j]]<f[i,b[j]] then f[i,b[j]]:=f[i-a[j],b[k]]+len[b[j]]-g[b[j],b[k]]; end; anss:=''; ans:=maxlongint; for i:=1 to n do if f[1 shl n-1,i]<ans then ans:=f[1 shl n-1,i]; dfs(1 shl n-1,1); writeln('Scenario #',l,':'); writeln(anss); writeln; end; end.