zoukankan      html  css  js  c++  java
  • 【BZOJ3676&UOJ103】回文串(manacher,Trie,回文自动机)

    题意:考虑一个只包含小写拉丁字母的字符串s。我们定义s的一个子串t的“出现值”为t在s中的出现次数乘以t的长度。

    请你求出s的所有回文子串中的最大出现值。

    len<=300000

    思路:

    做法一:manacher+Trie

    鸣谢UOJ上ID为nothing100的小哥(小姐姐?)

    学P一时爽,转C火葬场

    考虑不同的回文子串中间也是有子串关系的,并且互不包含的极长回文子串的数量是O(n)级别的

    所以可先用manacher算出每个位置的最长回文半径

    将它们表示成一棵树的形状,一个节点的儿子是它所代表的子串向两侧扩展一个相同字母的串

    判断是否是父子关系可以用hash 

    最后dfs一遍求子树大小就行了,注意需要双hash,C党hash后可以用map和makepair

    讲道理C党到这里就能做了,问题我是P党

    考虑到刚才那棵树,如果你每个串都只取后半段,那么它是一颗Trie树

    所以可以用和刚才类似的方法,而且并不需要hash

    manacher过程中

    i关于id的对称中心j,mx>i时:

    如果p[j]>mx-i则p[i]需要从p[j]开始退格,依次删除最后一个字符直到到达mx-i为止

    否则p[i]即为p[j]

    mx<=i时说明当前只有i一个字符,就从头开始扩展

    UOJ上过了,BZ上没过,残念……

     1 var map:array[1..610000,1..29]of longint;
     2     fa,size,p,f,a,h:array[1..610000]of longint;
     3     n,m,i,j,mx,id,cnt,len:longint;
     4     ans:int64;
     5     ch:char;
     6 
     7 function min(x,y:longint):longint;
     8 begin
     9  if x<y then exit(x);
    10  exit(y);
    11 end;
    12 
    13 function max(x,y:int64):int64;
    14 begin
    15  if x>y then exit(x);
    16  exit(y);
    17 end;
    18 
    19 function get(x,y:longint):longint;
    20 begin
    21  if map[x,y]=0 then
    22  begin
    23   inc(cnt);
    24   fa[cnt]:=x;
    25   map[x,y]:=cnt;
    26  end;
    27  exit(map[x,y]);
    28 end;
    29 
    30 procedure dfs(u,ch:longint;dep:int64);
    31 var i,v:longint;
    32 begin
    33  for i:=1 to 29 do
    34  begin
    35   v:=map[u,i];
    36   if v>0 then
    37   begin
    38    dfs(v,i,dep+1);
    39    size[u]:=size[u]+size[v];
    40   end;
    41  end;
    42  if ch<27 then ans:=max(ans,dep*size[u]);
    43 end;
    44 
    45 begin
    46  assign(input,'bzoj3676.in'); reset(input);
    47  assign(output,'bzoj3676.out'); rewrite(output);
    48 
    49  n:=2; a[1]:=27; a[2]:=28;
    50  while not eoln do
    51  begin
    52   read(ch);
    53   inc(n); a[n]:=ord(ch)-ord('a')+1;
    54   inc(n); a[n]:=28;
    55  end;
    56  inc(n); a[n]:=29;
    57  mx:=0; id:=0; cnt:=1;
    58  for i:=2 to n-1 do
    59  begin
    60   if mx>i then
    61   begin
    62    p[i]:=p[id*2-i]; h[i]:=h[id*2-i];
    63    if p[i]>mx-i then
    64    begin
    65     for j:=p[i]-1 downto mx-i do h[i]:=fa[h[i]];
    66     p[i]:=mx-i;
    67    end;
    68   end
    69    else
    70    begin
    71     h[i]:=get(1,a[i]);
    72     p[i]:=1;
    73    end;
    74   while a[i-p[i]]=a[i+p[i]] do
    75   begin
    76    h[i]:=get(h[i],a[i-p[i]]);
    77    inc(p[i]);
    78   end;
    79   if p[i]+i>mx then
    80   begin
    81    mx:=p[i]+i; id:=i;
    82   end;
    83   inc(size[h[i]]);
    84  end;
    85  dfs(1,27,0);
    86  writeln(ans);
    87  close(input);
    88  close(output);
    89 end.

     做法2:回文自动机板子

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 typedef unsigned int uint;
     5 typedef unsigned long long ull;
     6 typedef pair<int,int> PII;
     7 typedef pair<ll,ll> Pll;
     8 typedef vector<int> VI;
     9 typedef vector<PII> VII;
    10 typedef pair<ll,int>P;
    11 #define N  300010
    12 #define M  210000
    13 #define fi first
    14 #define se second
    15 #define MP make_pair
    16 #define pi acos(-1)
    17 #define mem(a,b) memset(a,b,sizeof(a))
    18 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
    19 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
    20 #define lowbit(x) x&(-x)
    21 #define Rand (rand()*(1<<16)+rand())
    22 #define id(x) ((x)<=B?(x):m-n/(x)+1)
    23 #define ls p<<1
    24 #define rs p<<1|1
    25 
    26 const int MOD=998244353,inv2=(MOD+1)/2;
    27       double eps=1e-6;
    28       int INF=1<<29;
    29       ll inf=5e13;
    30       int dx[4]={-1,1,0,0};
    31       int dy[4]={0,0,-1,1};
    32 
    33 char s[N];
    34 int n;
    35 
    36 struct pam
    37 {
    38     int q,p,id,cnt[N],num[N],f[N],len[N],t[N][26];
    39 
    40     pam()
    41     {
    42         id=1; f[0]=f[1]=1; len[1]=-1;
    43     }
    44 
    45     void add(int x,int n)
    46     {
    47             while(s[n-len[p]-1]!=s[n]) p=f[p];
    48         if(!t[p][x])
    49         {
    50                 int q=++id,k=f[p];
    51             len[q]=len[p]+2;
    52             while(s[n-len[k]-1]!=s[n]) k=f[k];
    53             f[q]=t[k][x];
    54             t[p][x]=q;
    55             num[q]=num[f[q]]+1;
    56         }
    57         p=t[p][x];
    58         cnt[p]++;
    59     }
    60 
    61     void solve()
    62     {
    63         ll ans=0;
    64         per(i,id,1)
    65         {
    66             cnt[f[i]]+=cnt[i];
    67             ans=max(ans,1ll*cnt[i]*len[i]);
    68         }
    69         printf("%lld
    ",ans);
    70     }
    71 
    72 }pam;
    73 
    74 int read()
    75 {
    76    int v=0,f=1;
    77    char c=getchar();
    78    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
    79    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
    80    return v*f;
    81 }
    82 
    83 int main()
    84 {
    85     //freopen("1.in","r",stdin);
    86 
    87     scanf("%s",s+1);
    88     n=strlen(s+1);
    89     rep(i,1,n) pam.add(s[i]-'a',i);
    90     pam.solve();
    91     return 0;
    92 }
  • 相关阅读:
    搜房二手频道调研
    智能评论排序
    国外社交网站调研(13年9月)
    百度金融产品的几点看法
    Microvideos for Website/ products
    C#后端代码访问webapi
    基于FineUI-FineUIMVC基础版开发的通用后台框架
    EasyUI, Dialog 在框架页(ifrmae)的Top页面弹出时,拖拽Dialog边缘(以改变窗口大小),UI界面被卡死的解决办法
    在Windows上使用Docker 创建MongoDB 副本集的极简方法(翻译)
    初探ABP--记一些常见的开发问题
  • 原文地址:https://www.cnblogs.com/myx12345/p/6710723.html
Copyright © 2011-2022 走看看