bzoj 3670 kmp

题意:定义num[i]表示:对字符串S的前i个字符组成的子串,既是它的前缀又是它的后缀且该前缀与后缀不重叠,满足条件的字符串的数量记做num[i],ans等于(num[i]+1)的累乘,对1000000007 取模

一看就是kmp..

再一看数据范围必须O(n)...所以一开始naive的对每个i都递归一下i=next[i]是妥妥的TLE的 QAQ

令 num[i]表示既是i前缀又是i后缀的子串个数

由kmp的性质可得 num[i]=num[next[i]]+1 

当然这个答案不一定是合法的,只需要从num[i-1]开始运用kmp的next往前跳,跳到第一个不大于(i/2)的位置p,ans*=num[p]+1

const
        mo=1000000007;
var
        t,p1,p2,l       :longint;
        ans             :qword;
        i               :longint;
        s               :ansistring;
        next,num        :array[0..1000010] of longint;
begin
   readln(t);
   while (t>0) do
   begin
      dec(t);
      readln(s);
      l:=length(s);
      fillchar(next,sizeof(next),0);
      fillchar(num,sizeof(num),0);
      p1:=0; p2:=0; ans:=1; num[1]:=1;
      for i:=2 to l do
      begin
         while (p1<>0) and (s[i]<>s[p1+1]) do p1:=next[p1];
         if (s[i]=s[p1+1]) then
         begin
            inc(p1);
            next[i]:=p1;
         end else next[i]:=0;
         //
         num[i]:=num[next[i]]+1;
         while (p2<>0) and (s[i]<>s[p2+1]) do p2:=next[p2];
         if s[i]=s[p2+1] then inc(p2);
         while (p2>(i>>1)) do p2:=next[p2];
         ans:=(ans*int64(num[p2]+1)) mod mo;
      end;
      writeln(ans);
   end;
end.

PS:mdzz,一开始看错题了,把题目中新定义的num数组当成“对字符串S的前i个字符组成的子串,既是它的前缀又是它的后缀且该前缀与后缀不重叠,满足条件的最长字符串”,对于这道看错了的题,答题思路和看对了的题是一样的,就是对num数组的定义是不一样的,这里定义num数组为看错了的所求,每一次跳到上一次的num[i-1]+1的位置,然后用next往前跳到第一个满足条件的位置就记录下来就可以了 。更尴尬的是这样错误的解法居然和样例只有最后一个字符串不一样,瞬间怀疑样例....

——by Eirlys




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值