AcWing 周赛十 隐藏字符串(思维+模拟)

链接

题意:

给定一个由小写字母构成的字符串 s。

我们称字符串 t 隐藏于字符串 s 中,如果它满足:

存在一个字符串 s 的子序列,与其一一对应。
该子序列的各个元素的下标可以构成一个等差序列。
例如,字符串 aab 就隐藏于字符串 aaabb 中,因为 aaabb 的第 1,3,5 个元素刚好可以构成 aab,而这恰好是一个公差为 2 的等差数列。

字符串 t 可能隐藏于字符串 s 中多次,这取决于共有多少个 s 的不同子序列满足与字符串 t 一一对应,且各个元素下标可以构成一个等差数列。

例如,在字符串 aaabb 中,a 隐藏了 3 次,b 隐藏了 2 次,ab 隐藏了 6 次…

现在,请你求出字符串 s 中,隐藏次数最多的字符串一共隐藏了多少次?

分析:

没有放自己理解的题意,放的原文的题意,也简单的。
首先我们看,要求最长的有两种情况,一种是长度为1的也就是只有一个字符,另一种是长度为2的字符串。
长度大于2的没有长度为2的优。这点随便举个例子就能知道,原因嘛就是他要求是等差数列。因为长度为2时,我们直接就可以任意两个都行,而长度大于2就不行,前两个固定了,后面也就固定了。所以长度大于2的字符串方案,只会比长度为2的差,不会比其更优。

那为什么有长度为1的那?这样看,如果字符串为aa那么最优方案数是2而不是1,长度为2是答案是1,而长度为1是答案是2所以我们需要记录下长度为1.

  • 长度为1,结果就是该字符的数量。
  • 长度为2,我们需要维护每次添加上一个字符后,会对结果造成多少贡献。 举个例子就像,我们看第i位上字符是'a',那么我们看他分别对 \(aa,ba,ca,da...za\)做的贡献,做好出贡献是多少那?是当前为位置之前有多少第一个字符的数量。就像前面有3个b那么我们对\(ba\)做出3贡献值、那如果前面有4个a那,做出的贡献是4而不是5,因为当前这个a只能当第二个字符。

之后就是 26*26找出最大的值即可。

// Problem: 隐藏字符串
// Contest: AcWing
// URL: https://www.acwing.com/problem/content/3792/
// Memory Limit: 256 MB
// Time Limit: 1000 ms
//
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef unsigned long long ull;

#define x first
#define y second
#define sf scanf
#define pf printf
#define PI acos(-1)
#define inf 0x3f3f3f3f
#define lowbit(x) ((-x)&x)
#define mem(a,x) memset(a,x,sizeof(a))
#define rep(i,n) for(int i=0;i<(n);++i)
#define repi(i,a,b) for(int i=int(a);i<=(b);++i)
#define repr(i,b,a) for(int i=int(b);i>=(a);--i)
#define debug(x) cout << #x << ": " << x << endl;

const int MOD = 998244353;
const int mod = 998244353;
const int maxn = 1e5 + 10;
const int dx[] = {0, 1, -1, 0, 0};
const int dy[] = {0, 0, 0, 1, -1};
const int dz[] = {1, -1, 0, 0, 0, 0 };
int day[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

string str;
ll a[50][50];
bool cmp(ll a, ll b)
{
    return a > b;
}
ll aa[26];
void solve()
{
    cin >> str;
    ll len = str.size();
    ll ans = 0;
    for(int i = 0; i < len; i++)
    {
        ll num = str[i] - 'a';
        for(int j=0;j<26;j++){
            a[j][num]+=aa[j];
        }        
        aa[num]++;
    }
    sort(aa,aa+26,cmp);
    ans=aa[0];
    for(int i=0;i<26;i++){
        for(int j=0;j<26;j++){
            ans=max(ans,a[i][j]);
        }
    }
    cout << ans << endl;
}

int main()
{
    ll t = 1;
    ///scanf("%lld",&t);
    while(t--) solve();
    return 0;
}
posted @ 2021-07-31 22:22  `KingZhang`  阅读(62)  评论(0)    收藏  举报