• 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 }
     
  • 相关阅读:
    C#通过反射获取类中的方法和参数个数,反射调用方法带参数
    C#利用WinRAR实现压缩和解压缩
    C# 使用HttpWebRequest Post提交数据,携带Cookie和相关参数示例
    C#使用Linq To XML读取XML,Linq生成XML,Linq创建带属性或带节点XML
    MVC使用Newtonsoft无需实体类,实现JSON数据返回给前端页面使用
    JSON对象与字符串之间的相互转换
    Javascript正则表达式详细讲解和示例,通俗易懂
    C#比较两个list集合,两集合同时存在或A集合存在B集合中无
    Uploadify 3.2上传文件,限制类型,大小,传递参数等
    c# 反射得到实体类的字段名称和值,DataTable转List<T>
  • 原文地址:https://www.cnblogs.com/ezyzy/p/6229401.html
Copyright © 2020-2023  润新知