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;
}

猜你喜欢

转载自blog.csdn.net/codeswarrior/article/details/80225684