F. Foreign Football-2022-2023 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2022)

Problem - F - Codeforces

题目大意:给一张足球比赛表,具有n行n列,每一个位置意味着一个队伍和另一个队伍的队伍名的合并,si+sj,当i==j时即自己和自己,为*。求这n个队伍的队伍名,当然有可能存在多种情况或者不存在。 

思路:1.n>=3时,存在公式,设所有队伍名称的长度和为len,那么一行来说就是len+(n-2)leni,那么所有的加起来就是(2*n-2)len,我们可以求出len,然后进而可以求出leni即每个队伍的队伍名长度。在其中判断是否不存在或者重复。

           2.n==2时,s[1][2]为a,s[2][1]为b,我们用b+b来当b,用kmp判断出a是否是b的一个子串。当然出现位置不能是0或者lena,如果这样的话说明a=b且中间没有任何可以截取的,说明只存在一支队伍另一只队伍不存在,所以位置数--,最后判断出现位置数除去这两个位置外是否还有其他的出现位置,并记录可能的出现位置。

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int maxn=2007;
string s[maxn][maxn];
int a[maxn];
string ans[maxn];
int n;
int ne[maxn*maxn];
char f[maxn*maxn],t[maxn*maxn];
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cin>>n;
    int len=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            cin>>s[i][j];
            if(s[i][j]!="*"){
                len+=s[i][j].length();
            }
        }
    }//len用于计算公式
    if(n>=3){//n>=3可用公式计算
        //cout<<len<<"\n";
        if(len%2==1||len%(2*n-2)!=0){
            cout<<"NONE"<<"\n";
            return 0;
        }//无法用公式计算的都是不存在的
        len/=(2*n-2);
        for(int i=1;i<=n;i++){
            int sum=0;
            for(int j=1;j<=n;j++){
                if(s[i][j]!="*"){
                    sum+=s[i][j].length();
                }
            }
            //cout<<sum<<"\n";
            if((sum-len)%(n-2)!=0){
                cout<<"NONE"<<"\n";
                return 0;
            }//找了半天的BUG,忘了除去n-2了,找了一天。。
            a[i]=max((sum-len)/(n-2),0LL);//有可能是0,当然都是NONE
            //cout<<a[i]<<"\n";
        }
        int flag=0;
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(s[i][j]!="*"){
                    if(s[i][j].size()<=a[i]){
                        //cout<<1<<"\n";
                        flag=1;
                        break;
                    }//无法截取时
                    string x=s[i][j].substr(0,a[i]);
                    string y=s[i][j].substr(a[i]);
                    if(ans[i]!=""&&ans[i]!=x){
                        //cout<<2<<"\n";
                        flag=1;
                        break;
                    }//同一个队伍有不同队伍名时
                    if(ans[j]!=""&&ans[j]!=y){
                        //cout<<3<<"\n";
                        flag=1;
                        break;
                    }
                    if(x==""||y==""){
                        //cout<<4<<"\n";
                        flag=1;
                        break;
                    }//有队伍为空串时
                    ans[i]=x;
                    ans[j]=y;
                }
            }
            if(flag)
            break;
        }
        if(flag){
            cout<<"NONE"<<"\n";
            return 0;
        }else{
            cout<<"UNIQUE"<<"\n";
            for(int i=1;i<=n;i++){
                cout<<ans[i]<<"\n";
            }
        }
    }else{//n==2时用kmp判断b+b中有没有a的子串,注意a=b的情况要减去
        if(s[1][2].size()==1||s[2][1].size()==1){
            cout<<"NONE"<<"\n";
            return 0;
        }//只有一个字符意味着另一只队伍没有名称。。
        for(int i=0;i<s[1][2].size();i++){
            f[i+1]=s[1][2][i];
        }//a串
        for(int i=0;i<s[2][1].size();i++){
            t[i+1]=s[2][1][i];
        }
        for(int i=s[2][1].size();i<2*s[2][1].size();i++){
            t[i+1]=s[2][1][i-s[2][1].size()];
        }//b+b串
        int len1=s[1][2].size(),len2=2*s[2][1].size();
        for(int i=2,j=0;i<=len1;i++){
            while(j&&f[i]!=f[j+1])
            j=ne[j];
            if(f[i]==f[j+1])
            j++;
            ne[i]=j;
        }//注意kmp
        int flag=0,num;
        for(int i=1,j=0;i<=len2;i++){
            while(j&&t[i]!=f[j+1])
            j=ne[j];
            if(t[i]==f[j+1])
            j++;
            if(j==len1){
                flag++;
                int k=i-len1;
                if(k==0||k==len1){
                    flag--;
                }
                if(k!=0&&k!=len1){
                    num=k;
                }
            }
        }//num为a串在b+b串中出现的位置,a=b要减去这两种情况
        if(flag>1){
            cout<<"MANY"<<"\n";
        }else if(!flag){
            cout<<"NONE"<<"\n";
        }else if(flag==1&&!num){
            cout<<"NONE"<<"\n";
        }else{
            cout<<"UNIQUE"<<"\n";
            string x=s[2][1].substr(0,num);
            string y=s[2][1].substr(num);
            cout<<y<<"\n";
            cout<<x<<"\n";
        }
    }
}

 代码有些臭,还是太菜。调了一天qwq..

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值