zoukankan      html  css  js  c++  java
  • bzoj 4032 [HEOI2015]最短不公共子串——后缀自动机

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4032

    不是 b 的子串的话就对 b 建后缀自动机,在 a 上枚举从每个位置开始的子串或者找子序列(子序列就是记录 a 的前 i 个,走到 b 的 j 状态用的最短长度),对应到自动机上看看能不能走下去就行了。

    不是 b 的子序列的话就对 b 建子序列自动机?就是那个知道每个位置再填一个字符会走到哪个位置的数组。然后在 a 上枚举,看看自动机上能不能走下去就行了。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N=2005,M=4005,K=30;
    char a[N],b[N];
    int n,m,cnt=1,lst=1,go[M][K],fa[M],l[M],nxt[N][K],lt[K];
    int dp[N][M];//M//int
    int Mn(int a,int b){return a<b?a:b;}
    void add(int w)
    {
      int p=lst,np=++cnt;lst=np;l[np]=l[p]+1;
      for(;p&&!go[p][w];p=fa[p])go[p][w]=np;
      if(!p)fa[np]=1;
      else
        {
          int q=go[p][w];
          if(l[q]==l[p]+1)fa[np]=q;
          else
        {
          int nq=++cnt;l[nq]=l[p]+1;
          fa[nq]=fa[q];fa[q]=nq;fa[np]=nq;
          memcpy(go[nq],go[q],sizeof go[q]);
          for(;go[p][w]==q;p=fa[p])go[p][w]=nq;
        }
        }
    }
    void solve1()
    {
      int ans=n+1;
      for(int i=1;i<=n;i++)
        {
          int cr=1;
          for(int j=i;j<=n;j++)
        {
          if(!go[cr][a[j]-'a'+1])
            {ans=Mn(ans,j-i+1);break;}
          cr=go[cr][a[j]-'a'+1];
        }
        }
      printf("%d
    ",ans>n?-1:ans);
    }
    void solve2()
    {
      int ans=n+1;
      for(int t=1;t<=n;t++)
        {
          int cr=0;
          for(int i=t;i<=n;i++)
        {
          int d=a[i]-'a'+1;
          if(nxt[cr][d])cr=nxt[cr][d];
          else {ans=Mn(ans,i-t+1);break;}
        }
        }
      printf("%d
    ",ans>n?-1:ans);
    }
    void solve3()
    {
      memset(dp,0x3f,sizeof dp);
      dp[0][1]=0; int ans=n+1;
      for(int i=1;i<=n;i++)
        {
          int d=a[i]-'a'+1;
          for(int j=1;j<=cnt;j++)
        if(dp[i-1][j]<=n)
        {
          dp[i][j]=Mn(dp[i][j],dp[i-1][j]);
          if(!go[j][d])ans=Mn(ans,dp[i-1][j]+1);
          else dp[i][go[j][d]]=Mn(dp[i][go[j][d]],dp[i-1][j]+1);
        }
        }
      printf("%d
    ",ans>n?-1:ans);
    }
    void solve4()
    {
      memset(dp,0x3f,sizeof dp);
      dp[0][0]=0; int ans=n+1;
      for(int i=1;i<=n;i++)
        {
          int d=a[i]-'a'+1;
          for(int j=0;j<=m;j++)
        if(dp[i-1][j]<=n)
          {
            dp[i][j]=Mn(dp[i][j],dp[i-1][j]);
            if(!nxt[j][d])ans=Mn(ans,dp[i-1][j]+1);
            else dp[i][nxt[j][d]]=Mn(dp[i][nxt[j][d]],dp[i-1][j]+1);
          }
        }
      printf("%d
    ",ans>n?-1:ans);
    }
    int main()
    {
      scanf("%s",a+1);scanf("%s",b+1);
      n=strlen(a+1);m=strlen(b+1);
      for(int i=1;i<=m;i++)add(b[i]-'a'+1);
      for(int i=m;i>=0;i--)
        {
          for(int j=1;j<=26;j++)
        nxt[i][j]=lt[j];
          lt[b[i]-'a'+1]=i;
        }
      solve1();solve2();
      solve3();solve4();
      return 0;
    }
  • 相关阅读:
    Sublime Text3 包管理器、插件安装
    Sublime text3 安装
    VS中的波浪线
    VS的启动方式
    VS常用快捷键
    C#基础性问题
    nginx前端项目发布
    vue父子组件实现数据双向绑定
    常用在线echarts图表
    使用echarts地图踩坑记
  • 原文地址:https://www.cnblogs.com/Narh/p/10108182.html
Copyright © 2011-2022 走看看