TJU1191-manacher回文串算法

小明最近在玩一种关于字符串的游戏,在这个游戏中,所有的字符串都是有小写英文字母(a-z)组成的。游戏中规定了每个字母的价值,这个价值用一个绝对值不超过100的整数表示(可以为正也可以为负)。一个字符串的价值等于构成这个字符串的所有字母的价值之和。比如,a的价值为-1,b的价值为0,c的价值为1时,字符串aabc的价值就是:(-1) + (-1) + 0 + 1 = -1。游戏的目标是,给定一个长度不超过500000的字符串,求这个字符串的一个价值最大的非空后缀,并且要求这个后缀是一个回文串。输出这个最大的权值。

输入格式

输入文件的第一行是26个整数,依次给出a到z这26个字母的价值。
输入文件的第二行是一个字符串,长度不超过500000。

输出格式

输出一个整数,即满足条件的价值最大的字符串的价值。

输入样例

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
dacaeaca

输出样例

7

数据规模与约定

对20%的数据,字串长度不超过1000
对100%的数据,字串长度不超过500000
每组测试数据时限1秒

题目来源天津市NOI选拔赛2009年第一轮
=============================================================================
模版题~不解释。

program suffix;

const
  MaxN = 1000001;

var
  str: array[1..MaxN] of char;
  Rad: array[1..MaxN] of longint;
  Sum: array[0..MaxN] of longint;
  Sco: array['a'..'z'] of longint;
  Len: longint;

  procedure Scan;
  var
    ch: char;
  begin
    for ch := 'a' to 'z' do
      Read(Sco[ch]);
    readln;

    Len    := 0;
    Sum[0] := 0;
    while not EOF do
    begin
      Read(ch);
      if (ch < 'a') or (ch > 'z') then
        continue;
      Inc(Len, 2);
      Str[Len - 1] := '#';
      Sum[Len - 1] := Sum[Len - 2];
      Str[Len]     := ch;
      Sum[Len]     := Sum[Len - 1] + Sco[ch];
    end;
    Inc(Len);
    Str[Len] := '#';
    Sum[Len] := Sum[Len - 1];
  end;

  function Min(a, b: longint): longint;
  begin
    if a < b then
      exit(a)
    else
      exit(b);
  end;

  procedure Manacher;
  var
    Mx, Id, i: longint;
  begin
    Mx := 0;
    for i := 1 to Len - 1 do
    begin
      if Mx > i then
        Rad[i] := Min(Rad[(Id shl 1) - i], Mx - i)
      else
        Rad[i] := 1;
      while Str[i - Rad[i]] = Str[i + Rad[i]] do
        Inc(Rad[i]);
      if Rad[i] + i > Mx then
      begin
        Mx := Rad[i] + i;
        Id := i;
      end;
    end;
  end;

  function Ans: longint;
  var
    i: longint;
  begin
    Ans := -maxlongint;
    for i := 1 to Len do
      if (i + Rad[i] > Len) and (Sum[Len] - Sum[i - Rad[i]] > Ans) then
        Ans := Sum[Len] - Sum[i - Rad[i]];
  end;

  procedure dubug;
  var
    i: longint;
  begin
    for i := 1 to Len do
      Write(Str[i]: 5);
    writeln;
    for i := 1 to Len do
      Write(Sum[i]: 5);
    writeln;
    for i := 1 to Len do
      Write(Rad[i]: 5);
    writeln;
  end;

  procedure Main;
  begin
    Scan;
    Manacher;
    Writeln(Ans);
    //dubug;
  end;

begin
  Assign(input, 'suffix.in');
  reset(input);
  Assign(output, 'suffix.out');
  rewrite(output);
  Main;
  Close(input);
  Close(output);
end.


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值