zoukankan      html  css  js  c++  java
  • 汕头市队赛 SRM19 字符题

    从天上掉下来了个这样的问题:

    有一个字符串 从中选出两个子串 A,B,求 A+B可以构成的不同串的个数。 还想知道,这么多个串中字典序最大的那一个。

    某人捡到了这个问题,并把它扔给了你。

    【输入】

    一个全由小写字母构成的字符串。

    【输出】

    第一行 一个非负整数,表示两个子串A+B可以构成的不同串个数。由于答案可能很大,所以答案对1004535809取模。

    第二行 一个字符串,表示构成的串中字典序最大的。

    【样例输入1】

    ab

    【样例输出1】

    11

    bb

    【样例输入2】

    abcaabccba

    【样例输出2】

    1428

    ccccba

    【数据范围及约定】

    n=|S|

    10% n<=10

    30% n<=40

    另有20%  字符串由1个a和n-1个b构成

    100% n<=2000

    【提示】

    两个子串均可为空,但不同时为空。

    这道题我们可以建一棵trie树记录所有子串 计算呢为了防止算重复

    我们可以枚举一个子串末尾加上某个字母后是否还是子串

    然后就搞来搞去就可以了 至于最大的话就跑一下字典序最大的子串

    前面再扔整个序列里面最大的那个字母 能扔几个是几个

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    const int M=5e3+7,mod=1004535809;
    int read(){
        int ans=0,f=1,c=getchar();
        while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
        while(c>='0'&&c<='9'){ans=ans*10+(c-'0'); c=getchar();}
        return ans*f;
    }
    char ch[M],ansq[M];
    int ans,s[M],cnt,n,cntq;
    int c[2000007][27];
    void insert(int k){
        int rt=0;
        for(int i=k;i<=n;i++){
            if(!c[rt][s[i]]) c[rt][s[i]]=++cnt;
            rt=c[rt][s[i]];
        }
    }
    int A[26],B[26];
    int dfs(int p){
        int sz=1;
        for(int i=0;i<26;i++){
            if(!c[p][i]) A[i]+=(p!=0);
            else if(!p) B[i]=dfs(c[p][i]);
            else sz+=dfs(c[p][i]);
        }
        return sz;
    }
    int main(){
        scanf("%s",ch+1);
        n=strlen(ch+1);
        for(int i=1;i<=n;i++) s[i]=ch[i]-'a';
        for(int i=1;i<=n;i++) insert(i);
        dfs(0);
        for(int i=0;i<26;i++) ans=(ans+1LL*(A[i]+1)*B[i]%mod)%mod;
        printf("%d
    ",ans);
        int rt=0;
        while(1){
            for(int i=25;i>=0;i--)if(c[rt][i]){
                ansq[++cntq]=i+'a';
                rt=c[rt][i]; goto o;
            }
            break;
            o:;
        }
        for(int i=1;i<=cntq;i++)
            if(ansq[i]==ansq[1]) putchar(ansq[i]);
            else break;
        printf("%s",(ansq+1));
        return 0;
    }
    View Code
  • 相关阅读:
    85. Maximal Rectangle
    120. Triangle
    72. Edit Distance
    39. Combination Sum
    44. Wildcard Matching
    138. Copy List with Random Pointer
    91. Decode Ways
    142. Linked List Cycle II
    异或的性质及应用
    64. Minimum Path Sum
  • 原文地址:https://www.cnblogs.com/lyzuikeai/p/7603400.html
Copyright © 2011-2022 走看看