zoukankan      html  css  js  c++  java
  • BZOJ2911 : [Poi1997]The Number of Symmetrical Choices

    新建源汇S,T,根据题意可以建出一个DAG

    设f[x][y]为从x走到y的回文路径的方案数,则

    边界条件:

    f[x][x]=1

    对于一条边x->y,若a[x]==a[y],则f[x][y]=1

    转移方程为:

    若a[x]==a[y],则f[x][y]=sum(f[i][j])(x->i有边,j->y有边)

    若a[x]!=a[y],则f[x][y]=0


    最终答案即为f[S][T],时间复杂度$O(L^2)$。

    #include<cstdio>
    #include<cstring>
    #define N 410
    int n,m,i,j,k,l,a[N],st[2][N],en[2][N],v[N][N],f[N][N];char s[N];
    struct E{int v;E*nxt;}*g[N],*h[N],pool[2000],*cur=pool;
    inline void add(int x,int y){
      E*p=cur++;p->v=y;p->nxt=g[x];g[x]=p;
      p=cur++;p->v=x;p->nxt=h[y];h[y]=p;
    }
    int F(int x,int y){
      if(v[x][y])return f[x][y];
      v[x][y]=1;
      if(a[x]!=a[y])return 0;
      for(E*p=g[x];p;p=p->nxt)for(E*q=h[y];q;q=q->nxt)f[x][y]+=F(p->v,q->v);
      return f[x][y];
    }
    int main(){
      scanf("%d",&n),m=2;
      for(k=0;k<2;k++)for(i=1;i<=n;i++){
        st[k][i]=m+1;
        for(scanf("%s",s+1),l=std::strlen(s+1),j=1;j<l;j++)add(m+j,m+j+1);
        for(j=1;j<=l;j++)a[m+j]=s[j]-'a'+1;
        en[k][i]=m+=l;
      }
      for(i=1;i<n;i++){
        add(en[0][i],st[0][i+1]);
        add(en[0][i],st[1][i+1]);
        add(en[1][i],st[0][i+1]);
        add(en[1][i],st[1][i+1]);
      }
      add(1,st[0][1]);
      add(1,st[1][1]);
      add(en[0][n],2);
      add(en[1][n],2);
      for(i=1;i<=m;i++){
        v[i][i]=f[i][i]=1;
        for(E*p=g[i];p;p=p->nxt){
          v[i][p->v]=1;
          if(a[i]==a[p->v])f[i][p->v]=1;
        }
      }
      return printf("%d",F(1,2)),0;
    }
    

      

  • 相关阅读:
    服务器带宽
    nload 源码安装
    Error: rpmdb open failed
    宽带,带宽,网速
    使用speedtest-cli测量服务器带宽
    ubuntu 安装 iperf
    微信退款机制
    记录程序执行之间,接口调用时间到日志文件或数据库
    机智的查询
    如果一些复杂的数据查询不好用数组,那就用字符串拼接,灵活方便
  • 原文地址:https://www.cnblogs.com/clrs97/p/4711876.html
Copyright © 2011-2022 走看看