小Y的字符串(拓展KMP)

本文详细介绍了如何使用拓展KMP算法解决字符串匹配问题,并通过具体实例演示了算法的实现过程。文章提供了完整的C++代码,解释了如何计算两个字符串间的最长公共前缀,特别适用于处理字符串a的所有后缀与字符串b之间的匹配。

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

题目链接:https://www.nowcoder.com/acm/contest/127/D

解题思路:拓展KMP,只要求出字符串b对字符串a每一个后缀的最长公共前缀即可


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <cmath>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>

using namespace std;

#define LL long long
const int INF = 0x3f3f3f3f;

int nt[2000009], extend[2000009];
char s1[2000009], s2[2000009];


void GetNext(char T[], int nt[]) {
      int t_len = strlen(T);
      nt[0] = t_len;
      int a, p;
      for (int i = 1, j = -1; i < t_len; i++, j--) {
        if (j < 0 || i + nt[i - a] >= p) {
          if (j < 0)
            p = i, j = 0;
          while (p < t_len && T[p] == T[j])
            p++, j++;
          nt[i] = j;
          a = i;
        }
        else nt[i] = nt[i - a];
      }
}

void GetExtend(char S[], char T[], int extend[], int nt[]) {
      GetNext(T, nt);
      int a, p;
      int s_len = strlen(S);
      int t_len = strlen(T);
      for (int i = 0, j = -1; i < s_len; i++, j--) {
        if (j < 0 || i + nt[i - a] >= p) {
          if (j < 0) p = i, j = 0;
          while (p < s_len && j < t_len && S[p] == T[j])
            p++, j++;
          extend[i] = j;
          a = i;
        }
        else extend[i] = nt[i - a];
      }
}

int main() {
  while (~scanf("%s %s", s1, s2)) {
    GetExtend(s1, s2, extend, nt);
    LL ans = 0;
    int len1 = strlen(s1), len2 = strlen(s2);
    for (int i = 0; s1[i]; i++) {
      if (extend[i] == len2) {
        ans = ans + 1LL * extend[i] - 1LL;
        if (s1[i + extend[i]] < s2[extend[i]]) {
          ans = ans + 1LL * len1 - 1LL * i -  1LL * extend[i];
        }
      } else {
        if (s1[i + extend[i]] < s2[extend[i]]) {
          ans = ans + 1LL * len1 - 1LL * i -  1LL * extend[i];
        }
        printf("%lld\n", ans);
      }
    }
    printf("%lld\n", ans);
  }
  return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值