zoukankan      html  css  js  c++  java
  • bzoj 3676 回文串 manachar+hash

           考虑每个回文串,它一定是它中心字母的最长回文串两侧去掉同样数量的字符后的一个子串。

           所以我们可以用manachar求出每一位的回文半径,放到哈希表里并标记出它的下一个子串。

           最后拓扑排序递推就行了。。。

           这道题丧心病狂卡哈希。。。。wa了一屏。。。

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<queue>
      6 #include<map>
      7 #define bas 131
      8 #define bs 31
      9 #define p 1000000007
     10 #define p2 986598521
     11 #define ll long long
     12 #define N 1200005
     13 using namespace std;
     14 char c[N],s[N*3];
     15 int hui[N],n;
     16 ll hash[N],pw[N],hash2[N],pw2[N];
     17 int head[1000005],nxt[N],tot,len[N],size[N],zhi[N];
     18 ll key[N],key2[N],nx[N],nx2[N];
     19 void insert(ll x,ll xx,int l,ll z,int ss,ll ww)
     20 {
     21     int y=x%1000003;
     22     tot++;nxt[tot]=head[y];head[y]=++tot;len[tot]=l;key[tot]=x;nx[tot]=z;zhi[tot]=ss;key2[tot]=xx;nx2[tot]=ww;
     23     return ;
     24 }
     25 int find(ll x,ll xx)
     26 {
     27     int y=x%1000003;
     28     for(int i=head[y];i;i=nxt[i])
     29     {
     30         if(key[i]==x&&key2[i]==xx)return i;
     31     }
     32     return 0;
     33 }
     34 int head2[N],ver2[N],nxt2[N],tot2;
     35 void add2(int x,int y)
     36 {
     37     tot2++;nxt2[tot2]=head2[x];head2[x]=tot2;ver2[tot2]=y;return ;
     38 }
     39 void manachar()
     40 {
     41     int mx=0,id=0;
     42     for(int i=1;i<=n;i++)
     43     {
     44         if(i>mx)
     45         {
     46             hui[i]=1;
     47             mx=i;id=i;
     48         }
     49         else
     50         {
     51             hui[i]=min(hui[id-(i-id)],mx-i+1);
     52         }
     53         int l=i-hui[i],r=i+hui[i];
     54         while(l!=0&&r!=n+1&&s[l]==s[r])
     55         {
     56              hui[i]++;
     57              mx=i+hui[i]-1;
     58              id=i;
     59              l--;r++;
     60         }
     61         int tmp=hui[i];
     62         if(s[i+hui[i]-1]=='#')tmp--;
     63         if(tmp==0)continue;
     64         int pos2=tmp+i-1,pos1=i-tmp+1;
     65         int lenn=(pos2-pos1)/2+1;
     66         ll haha,haha2;
     67         ll ha=(hash[pos2/2]-(hash[pos1/2-1]*pw[lenn])%p+p)%p;
     68         ll ha2=(hash2[pos2/2]-(hash2[pos1/2-1]*pw2[lenn])%p2+p2)%p2;
     69         if(pos2==pos1||pos2==pos1+2)haha=0,haha2=0;
     70         else haha=(hash[pos2/2-1]-(hash[pos1/2]*pw[lenn-2])%p+p)%p,haha2=(hash2[pos2/2-1]-(hash2[pos1/2]*pw2[lenn-2])%p2+p2)%p2;
     71         int k=find(ha,ha2);
     72         if(!k)insert(ha,ha2,lenn,haha,pos2/2,haha2),size[tot]++;
     73         else size[k]++;
     74     }
     75 }
     76 queue<int>qu;
     77 int ru[N];
     78 ll ans;
     79 void tupu()
     80 {
     81        for(int i=1;i<=tot;i++)if(!ru[i])qu.push(i);
     82     while(!qu.empty())
     83     {
     84         int tmp=qu.front();qu.pop();
     85         ans=max(ans,(ll)size[tmp]*len[tmp]);
     86         for(int i=head2[tmp];i;i=nxt2[i])
     87         {
     88             ru[ver2[i]]--;
     89             size[ver2[i]]+=size[tmp];
     90             if(!ru[ver2[i]])qu.push(ver2[i]);
     91         }
     92     }
     93 }
     94 int main()
     95 {
     96     scanf("%s",c+1);
     97     n=strlen(c+1);
     98     pw[0]=1;pw2[0]=1;
     99     for(int i=1;i<=n;i++)pw[i]=(pw[i-1]*bas)%p;
    100     for(int i=1;i<=n;i++)pw2[i]=(pw2[i-1]*bs)%p2;
    101     for(int i=1;i<=n;i++)hash[i]=(hash[i-1]*bas+c[i]-'a'+1)%p;
    102     for(int i=1;i<=n;i++)hash2[i]=(hash2[i-1]*bs+c[i]-'a'+1)%p2;
    103     for(int i=1;i<=n*2+1;i++)
    104     {
    105         if(i&1)s[i]='#';
    106         else s[i]=c[i/2];
    107     }
    108     n=n*2+1;
    109     manachar();
    110     for(int i=1;i<=tot;i++)
    111     {
    112         if(nx[i]==0)continue;
    113         int tmp=find(nx[i],nx2[i]);
    114         if(tmp!=0)add2(i,tmp),ru[tmp]++;
    115         else
    116         {
    117             ll now,now2;
    118             if(len[i]<=4)now=0,now2=0;
    119             else 
    120             {
    121                 now=(hash[zhi[i]-2]-(hash[zhi[i]-len[i]+2]*pw[len[i]-4])%p+p)%p;
    122                 now2=(hash2[zhi[i]-2]-(hash2[zhi[i]-len[i]+2]*pw2[len[i]-4])%p2+p2)%p2;
    123             }
    124             insert(nx[i],nx2[i],len[i]-2,now,zhi[i]-1,now2);
    125             add2(i,tot);ru[tot]++;
    126         }
    127     }
    128     tupu();
    129     printf("%lld
    ",ans);
    130     return 0;
    131 }
     
  • 相关阅读:
    Silverlight在线创建PDF(支持中文)
    ROR学习笔记(2):Asp.Net开发者看ROR
    Flash/Flex学习笔记(3):动态添加组件
    Flash/Flex学习笔记(2):捕获摄像头
    javascript中function调用时的参数检测常用办法
    Flash/Flex学习笔记(5):捕获摄像头(续)在线抓屏并保存到客户端本地
    ruby on rails + mysql 开发环境搭建
    再谈Silverlight中的对象序列化/反序列化
    温故而知新:设计模式之装饰模式(Decorator)
    选择一款适合自己的ruby on rails IDE开发工具
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6229401.html
Copyright © 2011-2022 走看看