zoukankan      html  css  js  c++  java
  • 字符串工厂

    字符串工厂

    定义两个字符串间的相似程度,为两个字符串中所有字符对(包括重复)的相似程度的和。字符对的相似程度已经给出。例如,(s[‘a’][‘a’]=s[‘b’][‘b’]=s[‘c’][‘c’]=2,s[‘a’][‘b’]=s[‘a’][‘c’]=1,s[‘b’][‘c’]=0)。则字符串”ab”与字符串”caa”的相似度为(s[‘a’][‘c’]+s[‘a’][‘a’]+s[‘a’][‘a’]+s[‘b’][‘c’]+s[‘b’][‘a’]+s[‘b’][‘a’]=1+2+2+0+1+1=7) 。现在给你n个字符串,求出它们两两之间的相似度之和(g(s1,s1)+g(s1,s2)+…g(s1,sn)+g(s2,s2)+g(s2,s3)+…+g(s2,sn)+…+g(sn,sn)),求出他们两两之间的相似度的平方和(g(s1,s1)^2+g(s1,s2)^2+…g(s1,sn)^2+g(s2,s2)^2+g(s2,s3)^2+…+g(s2,sn)^2+…+g(sn,sn))^2)。字符包括大小写字母或阿拉伯数字。(n<=1000,s[i][j]<=1000,字符串总长度S<=10^6)

    最暴力的枚举是(O(n^2Si^2))的,有20分。稍微不那么暴力一点的做法是预处理出每一个字符串,其中的每一种字符的个数,然后(O(n^2))枚举字符串,(O(62^2))求解,时间复杂度(O(n^262^2)),能拿40分。满分做法是首先(O(S)),预处理出每个字符串中每一种字符的个数,然后用(O(62^2n))的时间,求出一个字符对于一个字符串的相似度,最后用(O(62n^2))的时间,枚举一对字符串s1,s2,并算出s1中每种字符对于s2的相似度,然后把它们加起来,累加到答案中。于是正解是(O(S+62^2n+62n^2)),就过了。

    #include <cctype>
    #include <cstdio>
    #include <cstring>
    using namespace std;
    
    typedef long long LL;
    const int maxn=1e3+5, maxc=70, maxl=1e6+5, mod=1e9+7;
    int n, m, len, map[maxc][maxc], l[maxn];
    char* s[maxn]; char tmp[maxl];
    //c:字符串中出现的每种字符的数量 like:一个字符和字符串的相似度
    int c[maxn][62], like[maxn][62];
    LL ans1, ans2;
    
    inline int convert(char c){
        if (c>='0'&&c<='9') return c-'0';
        if (c>='A'&&c<='Z') return 10+c-'A';
        if (c>='a'&&c<='z') return 36+c-'a';
        return -1;
    }
    
    inline char rc(){
        char re;
        for (re=getchar(); !isgraph(re); re=getchar());
        return re;
    }
    
    inline char* rs(){
        scanf("%s", tmp); len=strlen(tmp);
        char *re=new char[len+1];
        memset(re, 0, len+1);
        for (int i=0; i<=len; ++i) re[i]=tmp[i];
        return re;
    }
    
    int main(){
        scanf("%d%d", &n, &m);
        char x, y; int w, t1, t2; LL tmp;
        for (int i=0; i<m; ++i){
            x=rc(); y=rc(); scanf("%d", &w);
            t1=convert(x); t2=convert(y);
            map[t1][t2]=map[t2][t1]=w;
        }
        for (int i=0; i<n; ++i){
            s[i]=rs(); l[i]=strlen(s[i]);
            for (int j=0; j<l[i]; ++j)
                ++c[i][convert(s[i][j])];
            for (int j=0; j<62; ++j)
                for (int k=0; k<62; ++k)
                    like[i][j]+=c[i][k]*map[j][k];
        }
        for (int i=0; i<n; ++i)
            for (int j=0; j<=i; ++j){
                tmp=0;
                for (int k=0; k<62; ++k)
                    tmp+=LL(c[j][k])*like[i][k];
                ans1=(ans1+tmp)%mod; ans2=(ans2+tmp*tmp)%mod;
            }
        printf("%lld
    %lld
    ", ans1, ans2);
        return 0;
    }
    
  • 相关阅读:
    C/C++取出变量的每一位的值(第一次知道还有QBitArray)
    什么样的程序员适合去创业公司
    VC2008如何生成及使用DLL(图文并茂,完整版)
    Qt浅谈之二十六图片滑动效果
    Qt 学习之路 2(75):线程总结
    Big Data Ingestion and streaming product introduction
    Qt学习之路(24): QPainter(改写paintEvent)
    Qt学习之路(54): 自定义拖放数据对象
    Qt学习之路(49): 通用算法
    Qt核心剖析: moc
  • 原文地址:https://www.cnblogs.com/MyNameIsPc/p/7774226.html
Copyright © 2011-2022 走看看