字符串工厂
定义两个字符串间的相似程度,为两个字符串中所有字符对(包括重复)的相似程度的和。字符对的相似程度已经给出。例如,(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;
}