zoukankan      html  css  js  c++  java
  • bzoj3654 图样图森破

    非常好的一道题

    我们把每个串正反拆成两个串,对于每个正串的所有节点,我们对他们和其他反串的起始位置进行判断lcp,如果这个节点后面的字符串和某个反串的lcp长度等于这个节点后面的字符串长度,那么我们就从这个节点向那个反串的开头连一个边权为二倍长度的边,如果lcp长度等于反串的总长时,我们就连向该节点后面的长度的节点,边权也是二倍lcp的长度,如果lcp不满的话,就连向T,都满的话,直接输出inf,另外,对于每个以串起始位置为左端点的回文串,我们从S向这个串后面的节点连边权为长度的边,可以发现这样在全图跑一个最长路就是最终的答案,如果有环就是inf;

    证明什么的比较显然,画画图就出来了。

    貌似还有更快的dfs做法,但是我不会。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <cmath>
      6 #include <queue>
      7 #define N 200505
      8 using namespace std;
      9 int n,m,len[105],zzh;
     10 char s[105][N];
     11 namespace graph{
     12     int e=1,head[N],S,pp[N];
     13     struct edge{
     14         int v,w,next;
     15     }ed[N<<7];
     16     void add(int u,int v,int w){
     17         if(u==v)return;
     18         if(v==S+1){
     19             if(pp[u]){ed[pp[u]].w=max(ed[pp[u]].w,w);return;}
     20             else pp[u]=e;
     21         }
     22         ed[e].v=v;ed[e].w=w;
     23         ed[e].next=head[u];head[u]=e++;
     24     }
     25     long long ans,D[N];
     26     bool vis[N],flag=0;
     27     void dfs(int x,long long dis){
     28         if(flag)return;
     29         D[x]=dis;ans=max(ans,dis);vis[x]=1;
     30         for(int i=head[x];i;i=ed[i].next){
     31             int v=ed[i].v;
     32             if(vis[v]){flag=1;return;}
     33             if(D[v]<=(long long)dis+ed[i].w)dfs(v,dis+ed[i].w);
     34         }vis[x]=0;
     35     }
     36     void work(){
     37         dfs(S,0);
     38         if(flag)puts("Infinity");
     39         else printf("%d
    ",ans);
     40     }
     41 }
     42 namespace manacher{
     43     int mx,pos,cnt,num[N],r[N],n;
     44     char s[N];
     45     void manacher(char *ch){
     46         n=strlen(ch);
     47         for(int i=0;i<n;i++)s[i]=ch[i];
     48         for(int i=n-1;~i;i--)s[2*i]=s[i],s[2*i+1]='#';n<<=1;
     49         mx=pos=cnt=0;
     50         num[++cnt]=0;
     51         for(int i=0;i<n;i++){
     52             if(i<mx)r[i]=min(r[2*pos-i],mx-i);
     53             else r[i]=1;
     54             while(i-r[i]>=0&&i+r[i]<n&&s[i-r[i]]==s[i+r[i]])r[i]++;
     55             if(i+r[i]>mx)pos=i,mx=i+r[i];
     56             if(i-r[i]+1==0)num[++cnt]=((i+r[i]-1)>>1)+1;
     57             if(i&1)graph::ans=max(graph::ans,(long long)(r[i]>>1)<<1);
     58             else graph::ans=max(graph::ans,(long long)(((r[i]+1)>>1)<<1)-1);
     59         }
     60     }
     61 }
     62 namespace sa{
     63     int buc[N],wa[N],wb[N];
     64     int sa[N],rank[N],height[N],r[N],n;
     65     char s[N];
     66     bool cmp(int *d,int a,int b,int c){
     67         return d[a]==d[b]&&d[a+c]==d[b+c];
     68     }
     69     void getheight(int n){
     70         int i,j,k=0;
     71         for(i=0;i<n;i++)rank[sa[i]]=i;
     72         for(i=0;i<n;height[rank[i++]]=k)
     73             for(k?k--:0,j=sa[rank[i]-1];r[i+k]==r[j+k];k++);
     74         return ;
     75     }
     76     void da(int n,int m=130){
     77         int i,j,p,*x=wa,*y=wb;
     78         for(i=0;i<m;i++)buc[i]=0;
     79         for(i=0;i<n;i++)buc[x[i]=r[i]]++;
     80         for(i=1;i<m;i++)buc[i]+=buc[i-1];
     81         for(i=n-1;~i;i--)sa[--buc[x[i]]]=i;
     82         for(j=1,p=0;p<n;j<<=1,m=p){
     83             for(p=0,i=n-j;i<n;i++)y[p++]=i;
     84             for(i=0;i<n;i++)if(sa[i]>=j)y[p++]=sa[i]-j;
     85             for(i=0;i<m;i++)buc[i]=0;
     86             for(i=0;i<n;i++)buc[x[y[i]]]++;
     87             for(i=1;i<m;i++)buc[i]+=buc[i-1];
     88             for(i=n-1;~i;i--)sa[--buc[x[y[i]]]]=y[i];
     89             for(swap(x,y),i=1,x[sa[0]]=0,p=1;i<n;i++)
     90                 x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
     91         }
     92         getheight(n);
     93     }
     94     int minn[N][20];
     95     void st_init(){
     96         for(int i=1;i<=n;i++)minn[i][0]=height[i];
     97         for(int j=1;(1<<j)<=n;j++)
     98             for(int i=1;i+(1<<j)-1<=n;i++)
     99                 minn[i][j]=min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]);
    100     }
    101     int work(){
    102         da(n+1);
    103         st_init();
    104     }
    105     int find(int x,int y){
    106         x=rank[x],y=rank[y];
    107         if(x>y)swap(x,y);x++;
    108         int k=0;
    109         while(x+(1<<k+1)-1<=y)k++;
    110         return min(minn[x][k],minn[y-(1<<k)+1][k]);
    111     }
    112 }
    113 int main(){
    114     scanf("%d",&n);
    115     for(int i=1;i<=n;i++){
    116         scanf("%s",s[++m]);
    117         len[m]=len[m+1]=strlen(s[m]);m++;
    118         for(int i=0;i<len[m];i++)
    119             s[m][i]=s[m-1][len[m]-1-i];
    120         len[m-1]+=len[m-2];len[m]+=len[m-1];
    121     }
    122     for(int i=1;i<=m;i++){
    123         for(int j=0;j<len[i]-len[i-1];j++)
    124             sa::r[sa::n++]=s[i][j];
    125         sa::r[sa::n++]='#';
    126     }
    127     memset(graph::pp,0,sizeof graph::pp);
    128     memset(graph::head,0,sizeof graph::head);
    129     sa::work();
    130     graph::S=len[m];
    131     for(int i=1;i<=m;i++){
    132         manacher::manacher(s[i]);
    133         for(int j=1;j<=manacher::cnt;j++)if(j==1||manacher::num[j]!=manacher::num[j-1]){
    134             if(manacher::num[j]==len[i]-len[i-1]){puts("Infinity");return 0;}
    135             graph::add(graph::S,len[i-1]+manacher::num[j],manacher::num[j]);
    136         }
    137         for(int j=0;j<len[i]-len[i-1];j++){
    138             for(int k=(i&1)?2:1;k<=m;k+=2){
    139                 int f=sa::find(len[i-1]+i-1+j,len[k-1]+k-1);
    140                 int l1=len[i]-len[i-1]-j,l2=len[k]-len[k-1];
    141                 if(f==l1&&f==l2){puts("Infinity");return 0;}
    142                 if(f){
    143                     if(f!=l1&&f!=l2)graph::add(len[i-1]+j,graph::S+1,2*f);                                   
    144                     if(f==l1)graph::add(len[i-1]+j,len[k-1]+(len[i]-len[i-1]-j),2*f);
    145                     if(f==l2)graph::add(len[i-1]+j,len[i-1]+j+f,2*f);
    146                 }
    147             }
    148         }
    149     }
    150     graph::work();
    151     return 0;
    152 }
    View Code
  • 相关阅读:
    JAVA IDE IntelliJ IDEA使用简介(一)—之界面元素
    ASP.NET MVC的运行机制--url的全局分析
    ASP.NET MVC
    [Android 新特性] 15项大改进 Android 4.4新特性解析
    [Android Pro] activity-alias的使用
    [Android Pro] 控制硬加速 hardwareAccelerated 在3.0才有的
    [Android Pro] Android中IntentService的原理及使用
    [SQLite] SQLite学习手册(数据库和事务)
    [Android UI] ActionBar 自定义属性
    [Android Memory] App调试内存泄露之Context篇(下)
  • 原文地址:https://www.cnblogs.com/Ren-Ivan/p/8370548.html
Copyright © 2011-2022 走看看