• bzoj4032: [HEOI2015]最短不公共子串(SAM+DP)


    4032: [HEOI2015]最短不公共子串

    题目:传送门 


    题解:

       陈年老题良心%你赛膜爆嘎爷

       当初做题...一眼SAM...结果只会两种直接DP的情况...

       情况1: 直接设f[i][j] 表示的是a串的第i个位置和b串的第j个位置开始的最长公共前缀(灵感来源于SA)。然后就枚举开头直接瞎搞啊。。。

       情况2: 定义一个last[i][j] 表示b串的位置i后面的第一个字符j,贪心的思想直接做,匹配不到位置就直接记录答案了嘛

       情况3: 因为是在b串当中找子串,a中找子序列,那就考虑对b建SAM,然后定义da[] 表示的是a串的第i个位置结尾的串在b串中跑到第j个状态的最短长度(具体看代码)、

       情况4: 利用情况2预处理的last,贪心思想,仿照情况三把last当作自动机来跑

        


    代码:

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<algorithm>
     6 #define inf 1e9 
     7 using namespace std;
     8 struct SAM
     9 {
    10     int son[50];
    11 }ch[5100];int cnt,dep[5100],a[5100],fail[5100],da[5100],la,root,ss;、
    12 //da 表示的是a串的第i个位置结尾的串在b串中跑到第j个状态的最短长度 
    13 void add(int k)
    14 {
    15     int x=a[k];
    16     int p=la,np=++cnt;dep[np]=k;
    17     while(p!=0 && ch[p].son[x]==0)ch[p].son[x]=np,p=fail[p];
    18     if(p==0)fail[np]=root;
    19     else
    20     {
    21         int q=ch[p].son[x];
    22         if(dep[p]+1==dep[q])fail[np]=q;
    23         else
    24         {
    25             int nq=++cnt;dep[nq]=dep[p]+1;
    26             ch[nq]=ch[q];fail[nq]=fail[q];fail[np]=fail[q]=nq;
    27             while(p && ch[p].son[x]==q)ch[p].son[x]=nq,p=fail[p];
    28         }
    29     }
    30     la=np;
    31 }
    32 int len1,len2,opt;
    33 int c[50],last[2100][50];//位置i后面的第一个字符j 
    34 char sa[2100],sb[2100];
    35 int f[2100][2100];//分别以i,j位置开头的最长公共前缀
    36 int main()
    37 {
    38     //freopen("a.in","r",stdin);
    39     //freopen("a.out","w",stdout);
    40     //scanf("%d",&opt);
    41     scanf("%s",sa+1);len1=strlen(sa+1);
    42     scanf("%s",sb+1);len2=strlen(sb+1);
    43     //if(opt==1)
    44     //{
    45         memset(f,0,sizeof(f));int ans=inf,len=0,maxx=0;
    46         for(int i=len1;i>=1;i--)for(int j=len2;j>=1;j--)if(sa[i]==sb[j])f[i][j]=f[i+1][j+1]+1;
    47         for(int i=1;i<=len1;i++)
    48         {        
    49             maxx=0;for(int j=1;j<=len2;j++)maxx=max(maxx,f[i][j]);
    50             if(maxx!=len1-i+1)ans=min(ans,maxx+1);//加一定不相等 
    51         }
    52         if(ans==inf)printf("-1
    ");
    53         else printf("%d
    ",ans);
    54     //}
    55     //else if(opt==2)
    56     //{
    57         len=0,ans=inf;for(int i=1;i<=50;i++)c[i]=inf;sb[0]='a';
    58         for(int i=len2;i>=0;i--){for(int j=1;j<=26;j++)last[i][j]=c[j];c[sb[i]-'a'+1]=i;}
    59         for(int i=1;i<=len1;i++)
    60         {
    61             len=0;
    62             for(int j=i;j<=len1;j++)
    63             {
    64                 len=last[len][sa[j]-'a'+1];
    65                 if(len>len1){ans=min(ans,j-i+1);break;}//跳出去证明没有了
    66             }
    67         }
    68         if(ans==inf)printf("-1
    ");
    69         else printf("%d
    ",ans);
    70     //}
    71 //    else if(opt==3)
    72 //    {
    73         cnt=0;root=la=++cnt;memset(da,63,sizeof(da));
    74         for(int i=1;i<=len2;i++)a[i]=sb[i]-'a';for(int i=1;i<=len2;i++)add(i);ss=0;da[1]=0;ans=inf;
    75         for(int i=1;i<=len1;i++)
    76             for(int j=1;j<=cnt;j++)
    77             {
    78                 ss=ch[j].son[sa[i]-'a'];
    79                 if(ss==0)ans=min(ans,da[j]+1);else da[ss]=min(da[ss],da[j]+1);
    80             }
    81         if(ans==inf)printf("-1
    ");
    82         else printf("%d
    ",ans);
    83 //    }
    84     //else if(opt==4)
    85     //{
    86         ans=inf;//for(int i=1;i<=50;i++)c[i]=inf;sb[0]='a';
    87         //for(int i=len2;i>=0;i--){for(int j=1;j<=26;j++)last[i][j]=c[j];c[sb[i]-'a'+1]=i;}
    88         memset(da,63,sizeof(da));da[0]=0;ss=0;
    89         for(int i=1;i<=len1;i++)
    90             for(int j=len2;j>=0;j--)
    91             {
    92                 ss=last[j][sa[i]-'a'+1];
    93                 if(ss>len1)ans=min(ans,da[j]+1);else da[ss]=min(da[ss],da[j]+1);
    94             }
    95         if(ans==inf)printf("-1
    ");
    96         else printf("%d
    ",ans);
    97     //}
    98     return 0;
    99 }
  • 相关阅读:
    shell (3) 磁盘挂载
    QByteArray 内存拷贝异常
    记录QTextEdit
    QTableWidget 使用
    QT 读写xml
    远程工具长时间待机断网解决办法
    qt读写json文件
    QT 资源文件(.qrc)
    error: C1041: 无法打开程序数据库“E:ProjectQtuild-QCaculator-Desktop_Qt_5_14_1_MSVC2017_32_bit-DebugdebugQCaculator.vc.pdb”;如果要将多个 CL.EXE 写入同一个 .PDB 文件,请使用 /FS
    Vs2019+Qt5.14环境配置,安装qt visual studio tools报错。
  • 原文地址:https://www.cnblogs.com/CHerish_OI/p/8783224.html
Copyright © 2020-2023  润新知