• bzoj2085


    首先看到k的范围就该知道这题不是倍增就是矩乘

    首先肯定要求出任意一对串(a,b) a的后缀与b的前缀相同的最长长度是多少

    考虑到kmp求出的失配指针是一个串最长后缀和前缀相等的长度

    这里多个串我们只要用ac自动机即可

    具体的,我们只要建立自动机,然后记录每个状态点是哪些串的子串

    然后我们只要从每个串的结尾节点出发,顺着失配指针统计即可

    然后我们把每个串看作一个点,点之间的边长度就是虽代表串的后缀前缀相同的最长长度

    这个问题等价于求经过k条边的最短长度,倍增轻松搞定

      1 const inf=2147483647*2147483647;
      2 type node=record
      3        po,next:longint;
      4      end;
      5      mtx=array[0..201,0..201] of int64;
      6 
      7 var lcp:array[0..201,0..201] of longint;
      8     d,p,w,fa,q:array[0..100010] of longint;
      9     loc:array[0..201] of longint;
     10     e:array[0..100010*200] of node;
     11     trie:array[0..100010,'a'..'z'] of longint;
     12     f,a:mtx;
     13     ss:ansistring;
     14     t,len,i,n,m,j,k:longint;
     15     ans:int64;
     16 
     17 function min(a,b:int64):int64;
     18   begin
     19     if a>b then exit(b) else exit(a);
     20   end;
     21 
     22 function max(a,b:longint):longint;
     23   begin
     24     if a>b then exit(a) else exit(b);
     25   end;
     26 
     27 procedure add(x,y:longint);
     28   begin
     29     inc(len);
     30     e[len].po:=y;
     31     e[len].next:=p[x];
     32     p[x]:=len;
     33   end;
     34 
     35 procedure ac;
     36   var h,r,x,y,j:longint;
     37       c:char;
     38   begin
     39     h:=1;
     40     r:=0;
     41     for c:='a' to 'z' do
     42       if trie[0,c]>0 then
     43       begin
     44         inc(r);
     45         q[r]:=trie[0,c];
     46       end;
     47 
     48     while h<=r do
     49     begin
     50       x:=q[h];
     51       for c:='a' to 'z' do
     52         if trie[x,c]>0 then
     53         begin
     54           y:=trie[x,c];
     55           inc(r);
     56           q[r]:=y;
     57           j:=fa[x];
     58           while (j>0) and (trie[j,c]=0) do j:=fa[j];
     59           fa[y]:=trie[j,c];
     60         end;
     61       inc(h);
     62     end;
     63   end;
     64 
     65 procedure get(k,x:longint);
     66   var i,j:longint;
     67   begin
     68     while fa[x]<>0 do
     69     begin
     70       x:=fa[x];
     71       i:=p[x];
     72       while i<>0 do
     73       begin
     74         j:=e[i].po;
     75         lcp[k,j]:=max(lcp[k,j],d[x]);
     76         i:=e[i].next;
     77       end;
     78     end;
     79   end;
     80 
     81 procedure mul(var c:mtx; a,b:mtx);
     82   var i,j,k:longint;
     83   begin
     84     for i:=1 to n do
     85       for j:=1 to n do
     86         c[i,j]:=inf;
     87 
     88     for k:=1 to n do
     89       for i:=1 to n do
     90         for j:=1 to n do
     91           c[i,j]:=min(c[i,j],a[i,k]+b[k,j]);
     92   end;
     93 
     94 begin
     95   readln(n,m);
     96   for i:=1 to n do
     97   begin
     98     readln(ss);
     99     w[i]:=length(ss);
    100     j:=0;
    101     for k:=1 to w[i] do
    102     begin
    103       if trie[j,ss[k]]=0 then
    104       begin
    105         inc(t);
    106         trie[j,ss[k]]:=t;
    107       end;
    108       j:=trie[j,ss[k]];
    109       d[j]:=k;
    110       add(j,i);
    111     end;
    112     loc[i]:=j;
    113   end;
    114   ac;
    115   for i:=1 to n do
    116     get(i,loc[i]);
    117   for i:=1 to n do
    118     for j:=1 to n do
    119       a[i,j]:=w[j]-lcp[i,j];
    120 
    121   for i:=1 to n do
    122     for j:=1 to n do
    123       if i<>j then f[i,j]:=inf;
    124   dec(m);
    125   while m>0 do
    126   begin
    127     if m mod 2=1 then mul(f,f,a);
    128     m:=m shr 1;
    129     mul(a,a,a);
    130   end;
    131   ans:=inf;
    132   for i:=1 to n do
    133     for j:=1 to n do
    134       ans:=min(ans,f[i,j]+w[i]);
    135   writeln(ans);
    136 end.
    View Code
  • 相关阅读:
    map初始化
    map
    sort排序
    455分发饼干
    392判断子序列
    vector遍历
    vector删除数据
    VC-进程间通信(InterProcess Communication,IPC)
    Oracle 11g 安装和登录(windows)
    控制台输出宽字符wchar_t的中文显示问题
  • 原文地址:https://www.cnblogs.com/phile/p/4533451.html
Copyright © 2020-2023  润新知