hdu 3613 扩展kmp求回文串

本文介绍了一种利用KMP算法处理字符串匹配问题的方法,并通过构造原串与反转串来寻找最长的前缀回文与后缀回文,进而解决特定问题。文中详细展示了如何通过C++实现该算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

新建一个串为给定串的反转,
原串跟新串匹配求得是前缀回文,
新串跟原串匹配求得是后缀回文。

#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<iostream>
#include<vector>
using namespace std;
int va[30],pre[510000],last[510000],nexta[510000],nextb[510000],l;
string a,b;
bool sumPre[510000],sumLast[510000];
void getNext(string a,int *nexta,int la)
{
       int i=0,j = -1;
       nexta[0] = -1;
       while(i<la)
       {
           if(a[i]==a[j]||j==-1)
           {
               i++,j++;
               nexta[i] = j;
           }
           else j = nexta[j];
       }
}
void kmp(string a,int la,string b,int *nexta,bool *sum)
{
      int i=0,j=0;
      while(j<l)
      {
          if(a[i]==b[j]||i==-1)
          {
              i++;j++;
          }
          else i = nexta[i];
      }
      int pre = i;
      while(pre)
      {
        sum[pre] = true;
        pre = nexta[pre];
      }
}
int main()
{
    int t;
    ios::sync_with_stdio(false);
    scanf("%d",&t);
    while(t--)
    {
        for(int i=0;i<26;i++) scanf("%d",&va[i]);
        cin>>a;
        l = a.size();
        int sum = 0;
        for(int i=0;i<=l;i++)
        {
            sumPre[i] = false;
            sumLast[i] = false;
        }
        for(int i=0;i<l;i++)
        {
            sum+=va[a[i]-'a'];
            pre[i] = sum;
        }
        sum = 0;
        for(int i=l-1;i>=0;i--)
        {
            sum+=va[a[i]-'a'];
            last[i] = sum;
        }
        b = a;
        reverse(b.begin(),b.end());
        getNext(a,nexta,l);
        kmp(a,l,b,nexta,sumPre);
        getNext(b,nextb,l);
        kmp(b,l,a,nextb,sumLast);
        int ans = -1000000000;
        for(int i=0;i<l-1;i++)
        {
            sum = 0;
            //printf("%d %d\n",sumPre[i+1],sumLast[l-i-1]);
            if(sumPre[i+1])sum+=pre[i];
            if(sumLast[l-i-1])sum+=last[i+1];
            ans = max(ans,sum);
        }
        printf("%d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值