1005 Programming Pattern (35 分)
解题思路:
队友一眼看出后缀数组+基数排序并手撸尝试,怎么搞都是T,百度了几份相同做法的代码同样T。
所以这里还是推荐哈希字符串,将字符串看成X进制的数(X>128,即所有字符的可能性),然后统计每一个字符串的编码用unordered_map(别用map) 存起来,采用线性计算,即下一个字符串的编码=(上一个字符串的编码-上一个字符×pow(X,位数-1))*X+新加进来的字符, 同时不断更新最大次数,以及统计最大次数的字符串下标,最后遍历所有满足的字符串,找字典序最小即可。
代码:
#include<bits/stdc++.h>
#include<unordered_map>
#include<unordered_set>
#define ll long long
#define pii pair<int,int>
#define pll pair<ll,ll>
#define mp make_pair
#define pb push_back
#define G 6.67430*1e-11
#define rd read()
#define pi 3.1415926535
using namespace std;
const ll mod = 998244353;
const int MAX1 = 100005;
const int MAX2 = 300005;
inline ll read() {
ll x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch>'9') {
if (ch == '-')
f = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
ll gcd(ll a, ll b) { return !b ? a : gcd(b, a % b); }
#define int ll
ll fpow(ll a, ll b)
{
ll ans = 1;
while (b)
{
if (b & 1)ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
string w;
unordered_map<ll, int> m;
vector<int> v;
string s;
ll ans = 0;
ll code = 0;
signed main()
{
int n = rd;
getline(cin, s);
const ll a = 43962200;
const ll b = fpow(a, n - 1) % mod;
for (int i = 0; i < s.size(); i++)
{
if (i >=n )
{
code = (code - s[i-n] * b%mod +mod) % mod;
}
code = (code * a + s[i]) % mod;
m[code]++;
if (m[code] >= ans)
{
if (m[code] != ans)
{
v.clear();
ans = m[code];
}
v.push_back(i);
}
}
string tmp,res;
for (auto p : v)
{
tmp = "";
for (int i = 0; i < n; i++)
{
tmp += s[i - n + p + 1 ];
}
res = res.size()?min(res, tmp):tmp;
}
cout << res << ' ' << ans;
return 0;
}