Codeforces Round 943 (Div. 3) G1. Division + LCP (easy version) 二分+KMP

Division + LCP (easy version)

题目描述

This is the easy version of the problem. In this version l = r l=r l=r .

You are given a string s s s . For a fixed k k k , consider a division of s s s into exactly k k k continuous substrings w 1 , … , w k w_1,\dots,w_k w1,,wk . Let f k f_k fk be the maximal possible L C P ( w 1 , … , w k ) LCP(w_1,\dots,w_k) LCP(w1,,wk) among all divisions.

L C P ( w 1 , … , w m ) LCP(w_1,\dots,w_m) LCP(w1,,wm) is the length of the Longest Common Prefix of the strings w 1 , … , w m w_1,\dots,w_m w1,,wm .

For example, if s = a b a b a b c a b s=abababcab s=abababcab and k = 4 k=4 k=4 , a possible division is a b a b a b c a b \color{red}{ab}\color{blue}{ab}\color{orange}{abc}\color{green}{ab} abababcab . The L C P ( a b , a b , a b c , a b ) LCP(\color{red}{ab},\color{blue}{ab},\color{orange}{abc},\color{green}{ab}) LCP(ab,ab,abc,ab) is 2 2 2 , since a b ab ab is the Longest Common Prefix of those four strings. Note that each substring consists of a continuous segment of characters and each character belongs to exactly one substring.

Your task is to find f l , f l + 1 , … , f r f_l,f_{l+1},\dots,f_r fl,fl+1,,fr . In this version l = r l=r l=r .

输入格式

The first line contains a single integer t t t ( 1 ≤ t ≤ 1 0 4 1 \le t \le 10^4 1t104 ) — the number of test cases.

The first line of each test case contains two integers n n n , l l l , r r r ( 1 ≤ l = r ≤ n ≤ 2 ⋅ 1 0 5 1 \le l = r \le n \le 2 \cdot 10^5 1l=rn2105 ) — the length of the string and the given range.

The second line of each test case contains string s s s of length n n n , all characters are lowercase English letters.

It is guaranteed that the sum of n n n over all test cases does not exceed 2 ⋅ 1 0 5 2\cdot 10^5 2105 .

输出格式

For each test case, output r − l + 1 r-l+1 rl+1 values: f l , … , f r f_l,\dots,f_r fl,,fr .

样例 #1

样例输入 #1

7
3 3 3
aba
3 3 3
aaa
7 2 2
abacaba
9 4 4
abababcab
10 1 1
codeforces
9 3 3
abafababa
5 3 3
zpozp

样例输出 #1

0
1
3
2
10
2
0

提示

In the first sample n = k n=k n=k , so the only division of a b a aba aba is a b a \color{red}a\color{blue}b\color{orange}a aba . The answer is zero, because those strings do not have a common prefix.

In the second sample, the only division is a a a \color{red}a\color{blue}a\color{orange}a aaa . Their longest common prefix is one.

原题

CF——传送门

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

int n, Left, Right;
const int MAX = 1e6 + 6;
int Next[MAX];
vector<int> ans;
inline void GetNext(string s, int l) // 获得字符串s的Next数组
{
    int t;
    Next[0] = -1;               // 如果在0位置失配则是向下移动一位
    for (int i = 1; i < l; ++i) // 依次求解后面的Next数组
    {
        t = Next[i - 1];
        while (s[t + 1] != s[i] && t >= 0)
            t = Next[t];
        if (s[t + 1] == s[i])
            Next[i] = t + 1;
        else
            Next[i] = -1;
    }
}
inline void KMP(string s1, int l1, string s2, int l2)
{
    GetNext(s2, l2);
    int i = 0, j = 0;
    while (j < l1)
    {
        if (s2[i] == s1[j]) // 当前位匹配成功,继续匹配下一位
        {
            ++i;
            ++j;
            if (i == l2) // 完全匹配
            {
                ans.push_back(j - l2); // 储存答案
                i = Next[i - 1] + 1;   // 继续匹配
            }
        }
        else
        {
            if (i == 0) // 在首位不匹配
                j++;
            else
                i = Next[i - 1] + 1;
        }
    }
}
bool check(string s, string a, int k)
{
    KMP(s, s.size(), a, a.size());
    int num = 0;
    // 去掉重叠的匹配子串
    if (ans.size() >= 1)
    {
        num++;
        int last = ans[0];
        for (int i = 1; i < ans.size(); i++)
        {
            if (ans[i] - last > k - 1)
            {
                num++;
                last = ans[i];
            }
        }
    }
    ans.clear();
    if (num >= Left)
        return 1;
    else
        return 0;
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int t;
    cin >> t;
    while (t--)
    {
        cin >> n >> Left >> Right;
        string s;
        cin >> s;
        // 二分
        int l = 0, r = n / Left;
        while (l < r)
        {
            int mid = (l + r + 1) / 2; // 这里要 l + r +1 要不然会死循环
            string a = s.substr(0, mid);
            if (check(s, a, mid)) // check函数自己写
            {
                l = mid; // mid这个位置 满足条件之后 查找 [mid , right]的位置, 所以l移到mid的位置
            }
            else
            {
                r = mid - 1; // [mid,r] 不满足条件, 所以要移到满足条件的一方, r = mid - 1
            }
        }
        cout << l << '\n';
    }

    return 0;
}

相关推荐

  1. Codeforces Round 913 (Div. 3) (A-G)

    2024-05-04 14:28:03       43 阅读
  2. Codeforces 923 div3 A-G

    2024-05-04 14:28:03       16 阅读
  3. cf-913-div3

    2024-05-04 14:28:03       68 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-04 14:28:03       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-04 14:28:03       106 阅读
  3. 在Django里面运行非项目文件

    2024-05-04 14:28:03       87 阅读
  4. Python语言-面向对象

    2024-05-04 14:28:03       96 阅读

热门阅读

  1. AT_abc348_d [ABC348D] Medicines on Grid 题解

    2024-05-04 14:28:03       36 阅读
  2. PostgreSQL自带的命令行工具06- pg_isready

    2024-05-04 14:28:03       32 阅读
  3. u-boot引导加载程序的命令列表

    2024-05-04 14:28:03       34 阅读
  4. 边缘计算概述_2.边缘计算的特点

    2024-05-04 14:28:03       38 阅读
  5. 牛客Xorto

    2024-05-04 14:28:03       30 阅读
  6. 附录C:招聘流程

    2024-05-04 14:28:03       27 阅读
  7. 2011NOIP普及组真题 2. 统计单词数

    2024-05-04 14:28:03       34 阅读
  8. 江西省建设工程专业技术人员职称申报条件

    2024-05-04 14:28:03       34 阅读
  9. 非关系型数据库-Redis

    2024-05-04 14:28:03       24 阅读