zoukankan      html  css  js  c++  java
  • jzoj2742. 【PKU1625】Censored!

    Description

    给出p个长度不超过10的字符串,字符集大小为n。
    如果这p个串都不是字符串s的子串,则认为s是幸运的。
    求长度为m的幸运串个数。

    Input

    第一行三个正整数n,m,p。
    第二行n个不同的字符,表示字符集,其ASCII码大于32。
    接下来p行每行一个字符串,表示不允许被包含的串。

    Output

    一行一个整数,表示幸运串个数。

    Sample Input

    2 3 1
    ab
    bb

    Sample Output

    5

    Data Constraint

    对于20%的数据,m ≤ 6,n ≤ 10;
    对于50%的数据,p个串的长度不超过4,m ≤ 50,n ≤ 10;
    对于100%的数据,n ≤ 50,m ≤ 50,p ≤ 10。

    Hint

    aaa aab aba baa bab 共5个串为幸运串。

    题解

    这题首先我们看到找出p字符串不为子串的字符串方案数。
    想到什么?AC_Automation of course
    如果不会AC_Automation也就是AC自动机的话,先学学也可。
    其实这玩意就是trie+kmp。
    于是我们把p字符串建立一颗AC自动机,然后在结尾挂上一个标记(注意fail边要下传!!!)
    接下来我们考虑DP
    f[i,j]f_{[i,j]}表示当前建立新字符串建到第ii位时,AC自动机上走到了jj这个位置。
    初始化f[0,0]=1f_{[0,0]}=1
    然后我们枚举i1i-1走到了jj状态,再枚举当前位放第kk个字符。
    然后跳fail链,跳到的位置记为lastlast。同时判断一下有没有走到标记即可
    方程:
    f[i,last]+=f[i1,j]f_{[i,last]}+=f_{[i-1,j]}
    很清真,很简单。
    然后出题人就硬是要你套个高精度加法。
    时间复杂度:O(mnlen(p)x())O(m*n*len(表示p字符串总大小)*x(高精度的时间))

    代码

    uses math;
    var
            i,j,k,l,n,m,p,tot:longint;
            id:array[1..1000] of longint;
            tree:array[0..5000,0..200] of longint;
            d,next:array[0..50000] of longint;
            an,ka,kb:array[1..200] of longint;
            f:array[0..100,0..200] of ansistring;
            bz:array[1..5000] of boolean;
            s,c:string;
            ans:ansistring;
    function jia(a,b:ansistring):ansistring;
    var
            i,j,k,l,lena,lenb,len:longint;
            c:ansistring;
    begin
            lena:=length(a);lenb:=length(b);
            if (lena>lenb) or ((lena=lenb) and (a>b)) then
            begin
                    c:=a;a:=b;b:=c;
                    l:=lena;lena:=lenb;lenb:=l;
            end;
            j:=1;for i:=1 to lena do begin ka[i]:=ord(a[j])-48; inc(j); end;
            j:=1;for i:=1 to lenb do begin kb[i]:=ord(b[j])-48; inc(j); end;
            an:=kb;
            k:=0;j:=0;l:=lenb;
            for i:=lena downto 1 do
            begin
                    j:=ka[i]+kb[l]+k;
                    k:=j div 10;
                    j:=j mod 10;
                    an[l]:=j;
                    dec(l);
            end;
            c:='';
            while k>0 do
            begin
                    if l>0 then
                    begin
                            j:=kb[l]+k;
                            k:=j div 10;
                            j:=j mod 10;
                            an[l]:=j;
                            dec(l);
                    end
                    else
                    begin
                            c:=c+chr(k+48);
                            break;
                    end;
            end;
            for i:=1 to lenb do
            begin
                    c:=c+chr(an[i]+48);
            end;
            exit(c);
    end;
    procedure build_ac_automation;
    var
            i,j,k,l,head,tail,took,x,y,dep:longint;
    begin
            head:=1;
            tail:=1;
            took:=1;
            repeat
                    for dep:=head to tail do
                    begin
                            for i:=1 to n do
                            begin
                                    if tree[d[dep],i]>0 then
                                    begin
                                            y:=tree[d[dep],i];
                                            x:=next[d[dep]];
                                            while (x>0) and (tree[x,i]=0) do x:=next[x];
                                            if d[dep]>0 then
                                            begin
                                                    next[y]:=tree[x,i];
                                            end;
                                            if y<>tree[x,i] then
                                            begin
                                                    if bz[tree[x,i]] then bz[y]:=true;
                                            end;
                                            inc(took);
                                            d[took]:=y;
                                    end;
                            end;
                    end;
                    head:=tail+1;
                    tail:=took;
            until head>tail;
    end;
    procedure trie(x,i,up:longint);
    var
            j,k,l:longint;
    begin
            if i=up then
            begin
                    bz[x]:=true;
                    exit;
            end;
            if tree[x,id[ord(s[i+1])]]>0 then
            begin
                    trie(tree[x,id[ord(s[i+1])]],i+1,up);
            end
            else
            begin
                    inc(tot);
                    tree[x,id[ord(s[i+1])]]:=tot;
                    trie(tree[x,id[ord(s[i+1])]],i+1,up);
            end;
    end;
    begin
            //assign(input,'consored.in');reset(input);
            readln(n,m,p);
            readln(c);
            tot:=0;
            for i:=1 to n do
            begin
                    inc(tot);
                    id[ord(c[i])]:=tot;
                    tree[0,tot]:=tot;
            end;
            for i:=1 to p do
            begin
                    readln(s);
                    trie(0,0,length(s));
            end;
            build_ac_automation;
            f[0,0]:='1';
            for i:=1 to m do
            begin
                    for j:=0 to tot do
                    begin
                            if (length(f[i-1,j])>0) then
                            begin
                                    for k:=1 to n do
                                    begin
                                            l:=j;
                                            while (l>0) and (tree[l,k]=0) do l:=next[l];
                                            if not bz[tree[l,k]] then
                                            begin
                                                    if (length(f[i,tree[l,k]])=0) then f[i,tree[l,k]]:='0';
                                                    f[i,tree[l,k]]:=jia(f[i,tree[l,k]],f[i-1,j]);
                                            end;
                                    end;
                            end;
                    end;
            end;
            for i:=1 to tot do
            begin
                    ans:=jia(ans,f[m,i]);
            end;
            writeln(ans);
    end.
    
  • 相关阅读:
    ListComparer
    C#.net中类与结构的区别
    对C# 中堆栈,堆,值类型,引用类型的理解
    一道面试题
    Mvc不等于三层架构
    SQL养成一个好习惯是一笔财富
    清除MSSQL事务日志文件
    面向对象设计(OOD)五大基本原则
    .net/c#中栈和堆的区别及代码在栈和堆中的执行流程详解之一
    IIS7 Login failed for user IIS APPPOOL\ASP.NET v4.0
  • 原文地址:https://www.cnblogs.com/RainbowCrown/p/11148358.html
Copyright © 2011-2022 走看看