Two-gram (暴力选子串+kmp)

Two-gram

Two-gram is an ordered pair (i.e. string of length two) of capital Latin letters. For example, “AZ“, “AA“, “ZA” — three distinct two-grams.

You are given a string s

consisting of
n capital Latin letters. Your task is to find
any two-gram contained in the given string
as a substring (i.e. two consecutive characters of the string) maximal number of times. For example, for string
s = “
BBAABBBA” the answer is two-gram “
BB“, which contained in
s

three times. In other words, find any most frequent two-gram.

Note that occurrences of the two-gram can overlap with each other.

Input

The first line of the input contains integer number n

(
2n100) — the length of string
s. The second line of the input contains the string
s consisting of
n

capital Latin letters.

Output

Print the only line containing exactly two capital Latin letters — any two-gram contained in the given string s

as a substring (i.e. two consecutive characters of the string) maximal number of times.

Examples Input

7
ABACABA

Output

AB

Input

5
ZZZAA

Output

ZZ

Note

In the first example “BA” is also valid answer.

In the second example the only two-gram “ZZ” can be printed because it contained in the string “ZZZAA” two times.

子串长度是2,所以直接暴力选子串,然后kmp匹配不断更新出现次数最多的子串为答案

我的思路很简单,暴力枚举子串,kmp找出现次数,写起来相对复杂,当然也可以暴力找出现次数时间复杂度都是可以的

code:

#include <bits/stdc++.h>
using namespace std;
int n;
char s[120];
char w[4];
char ans[4];
int Next[120];
int maxt;
void getNext(){
    int i = -1,j = 0;
    Next[0] = -1;
    while(j < 2){
        if(i == -1 || w[i] == w[j]){
            i++,j++;
            if(w[i] == w[j]) Next[j] = Next[i];
            else Next[j] = i;
        }
        else
            i = Next[i];
    }
}
void kmp(){
    getNext();
    int i = 0,j = 0;
    int cnt = 0;
    while(j < n){
        if(i == -1 || s[j] == w[i]){
            i++,j++;
        }
        else
            i = Next[i];
        if(i == 2) cnt++;
    }
    if(cnt > maxt){
        maxt = cnt;
        strcpy(ans,w);
    }
}
int main(){
    scanf("%d",&n);
    scanf("%s",s);
    maxt = 0;
    for(int i = 0; i < n-1; i++){
        w[0] = s[i];
        w[1] = s[i+1];
        w[2] = 0;
        kmp();
    }
    printf("%s\n",ans);
    return 0;
}

下面是我队友的巧妙思路

code:

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int dp[30][30];
int main(){
    int n;
    string str;
    cin >> n >> str;
    for(int i = 0; i < n-1; i++){
        int x = str[i] - 'A';
        int y = str[i+1] - 'A';
        dp[x][y]++;
    }
    int maxt = 0,Last = 0,Next = 0;
    for(int i = 0; i < 26; i++){
        for(int j = 0; j < 26; j++){
            if(maxt < dp[i][j]){
                Last = i;
                Next = j;
                maxt = dp[i][j];
            }
        }
    }
    printf("%c%c\n",Last + 'A',Next + 'A');
    return 0;
}

    原文作者:KMP算法
    原文地址: https://blog.csdn.net/codeswarrior/article/details/80225684
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞