Codeforces Round #541 (Div. 2) E 字符串 + 思维 + 猜性质

https://codeforces.com/contest/1131/problem/D

题意

给你n个字符串,字符串长度总和加起来不会超过1e5,定义字符串相乘为\(s*s1=s1+s[0]+s1+s[1]+s1+...+s1+s[size-1]+s1+s[size]+s1\),求n个字符串依次相乘后最长连续字符相同的子序列长度

题解

  • 鬼畜的题意 or 难以优化的复杂度,都需要观察性质才能做,第二串要插入第一个串每个字符之间,可以看出字符数增长的速度很快,所以并不能把整个字符存下来
  • 只看一种字符的话,最优选择肯定是将后面的串插进前面串最长子序列之间
  • 分两种情况看,假设当前答案为len,cal()为计算当前字符串最长子序列函数,front()为最长前缀,back()为最长后缀
    • 假如第二串是由同一字符组成,那么len=|s2|*(len+1)+len
    • 反之,len=max(cal(s2),front(s2)+back(s2)+1),答案可能在为s2中,或者两个s2夹着一个s1的字符

代码

#include<bits/stdc++.h>
#define M 100005
using namespace std;
string s[M];
int i,j,n,tp,ans;

int ft(int p,char c){
    int cnt=0;
    for(int i=0;i<s[p].size();i++){
        if(s[p][i]==c)cnt++;
        else return cnt;
    }
}
int bk(int p,char c){
    int cnt=0;
    for(int i=s[p].size()-1;i>=0;i--){
         if(s[p][i]==c)cnt++;
         else return cnt;
    }
}
int cal(int p,char c){
    int cnt=0,ans=0;
    for(int i=0;i<s[p].size();i++){
        if(s[p][i]==c)cnt++;
        else cnt=0;
        ans=max(ans,cnt);
    }
    return ans;
}
int ck(int p,char c){
    for(int i=0;i<s[p].size();i++){
        if(s[p][i]!=c)return 0;
    }
    return 1;
}
int main(){
    cin>>n;
    for(i=1;i<=n;i++)cin>>s[i];
    for(i=0;i<26;i++){
        tp=0;
        for(j=1;j<=n;j++){
            if(tp==0){
                tp=cal(j,i+'a');
            }else{
                if(ck(j,i+'a'))
                   tp+=cal(j,i+'a')*(tp+1);
                else
                   tp=max(cal(j,i+'a'),ft(j,i+'a')+bk(j,i+'a')+1);
            }
            /*if(tp>ans){
                cout<<i<<" "<<j<<" "<<tp<<endl;
                ans=max(ans,tp);
            }
            */
        }
        ans=max(ans,tp);
    }
    cout<<ans;
}

原文地址:https://www.cnblogs.com/VIrtu0s0/p/10509884.html

时间: 2024-11-06 22:05:43

Codeforces Round #541 (Div. 2) E 字符串 + 思维 + 猜性质的相关文章

Codeforces Round #541 (Div. 2) 题解

Codeforces Round #541 (Div. 2) 题目链接:https://codeforces.com/contest/1131 A. Sea Battle 题意: 给出两个矩形的宽和高,满足第一个矩形的左上顶点为(0,0),右下顶点为(w1,-h1):第二个矩形的坐下顶点为(0,0),右上顶点为(w2,h2).然后求围绕这两个矩形一圈的格子个数为多少. 题解: 利用二维前缀和的思路推导一下公式就行了,公式也有很多吧==我当时就是大概模拟了一下.. 代码如下: #include <

Codeforces Round #424 (Div. 2) D 思维 E set应用,树状数组

Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals) D. Office Keys 题意:一条直线上,有个办公室坐标 p,有 n个人在a[i],有 k把钥匙在b[i],每个人必须拿到一把钥匙,然后到办公室.问怎么安排花的时间最短. tags:还是不懂套路啊..其实多画两下图就能够感觉出来,2333 关键是要看出来,n个人拿的 n把钥匙应该是连续的. 然后,就是瞎暴力.. #include<bits/stdc++.h> usi

Codeforces Round #546 (Div. 2) D 贪心 + 思维

https://codeforces.com/contest/1136/problem/D 贪心 + 思维 题意 你面前有一个队列,加上你有n个人(n<=3e5),有m(m<=个交换法则,假如u在v相邻前面,那么u和v可以交换位置,问你是队列最后一个人的时候你最前可以换到前面哪里 题解 因为相邻才能换,所以最后一个换到前面一定是一步一步向前走,所以不存在还要向后走的情况 设最后一个为u,假设前面有一个能和u换位置的集合,那么需要将这些点尽量往后移动去接u 假设前面有一个不能和u换位置的集合S,

Codeforces Round #541 (Div. 2) (A~F)

目录 Codeforces 1131 A.Sea Battle B.Draw! C.Birthday D.Gourmet choice(拓扑排序) E.String Multiplication(思路) F.Asya And Kittens(链表) G.Most Dangerous Shark Codeforces 1131 比赛链接 hack一个暴力失败了两次最后还是没成功身败名裂= = CF跑的也太快了吧... 不过倒也涨了不少. A.Sea Battle //想麻烦了,但是无所谓... #

Codeforces Round #297 (Div. 2)(模拟+字符串+排序)

A. 题目链接:点击打开链接 解题思路: 大意就是说奇数位给小写字母,偶数位给大写字母,然后小写对应钥匙,大写对应门,问最少消耗几把钥匙能打开所有门. 简单模拟即可,初始化一个英文字母数组,如果遇到小写字母,我们把相应的计数器++,遇到大写,如果它对应的数组值不为0,那么我们将其--, 否则购买一把钥匙. 完整代码: #include <iostream> #include <cstdio> #include <algorithm> #include <cstri

Codeforces Round #541 (Div. 2) D 并查集 + 拓扑排序

https://codeforces.com/contest/1131/problem/D 题意 给你一个n*m二维偏序表,代表x[i]和y[j]的大小关系,根据表构造大小分别为n,m的x[],y[],使得两个数组中最大的数尽量小 题解 按照偏序表,构造出从小到大的拓扑图 如何解决相等的数的偏序关系? 用并查集缩点后再进行拓扑排序 如何解决最大的数最小? 只需要使得同一层的数相同就行,可以一批处理栈中的元素,对于一批栈中的元素产生的新点,先放进一个容器里,然后等到这批栈清空了,再把这个容器中的点

Codeforces Round #566 (Div. 2)C(字符串,SET)

#include<bits/stdc++.h>using namespace std;string s[100007];set<int>st[100007][7];int t[207];int a[100007],b[100007][2],c[100007],d[100007][2];int main(){ t['a']=1; t['e']=2; t['i']=3; t['o']=4; t['u']=5; int n; cin>>n; for(int i=1;i<

codeforces Round #541 (Div 2)

A Sea Battle 平移过后即外围的$(w_{2} + 2) \times  (h_{1} + h_{2} + 2)$的矩形周长; 1 #include<bits/stdc++.h> 2 using namespace std; 3 int main(){ 4 int w1,w2,h1,h2; 5 cin>>w1>>h1>>w2>>h2; 6 int a=w1+2,b=h1+h2+2; 7 cout<<((a+b)<<

Codeforces Round #581 (Div. 2)D(思维,构造,最长非递减01串)

#define HAVE_STRUCT_TIMESPEC#include<bits/stdc++.h>using namespace std;char s[100007];int main(){ cin>>s+1; int n=strlen(s+1); int cnt=0; for(int i=n;i>=1;--i){//从后向前,保证后面的解都是合法的情况下 if(s[i]=='1'){//如果当前位置的数字是1 if(cnt)//i后面1的个数小于0的个数,此时如果把i位