题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6034
题意:
有n个只有小写英文字母组成的字符串,给26个字母一个[0, 25]的映射,使得当把字符串看成是26进制的串时,所有串加起来的和最大。
思路:
用一个二维数组L[26][maxn], 把每种字母在每个位上的个数统计出来,满26进位,把这个数组的每一行看成是一个26进制的数,那么我们给最大的那个数所对应的字母25,依次类推。
值得注意的是题目中,26个字母中至少有一个没有出现在串首,如果我们给出现在串首的字母分配为0是不对的,此时应该把没有出现在串首的字母分配为0。
排序方法:把L数组转换成字符串,先按长度排序,长度相同的按ascii码排序。
代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <string>
#include <cstdio>
#include <vector>
#include <map>
using namespace std;
const int maxn = 1e5+100;
const int MAXN = 1e6+100;
const int mod = 1e9+7;
struct Node
{
string ss;
int idx;
Node(){}
Node(string &ss, int idx):ss(ss), idx(idx){}
bool operator<(const Node &rhs)const{
if(this->ss.size()>rhs.ss.size()) return true;
else if(this->ss.size()==rhs.ss.size()){
return this->ss > rhs.ss;
}
else return false;
}
}A[30];
char inp[maxn];
int n, Case, mp[30], L[30][MAXN], len[30];
bool vis[30], another_vis[30];
void init(){
memset(L, 0, sizeof(L));
memset(len, 0, sizeof(len));
memset(vis, 0, sizeof(vis));
memset(another_vis, 0, sizeof(another_vis));
for(int i=0; i<30; ++i) mp[i] = -1;
for(int i=0; i<30; ++i) {A[i].ss = ""; A[i].idx=-1;}
}
void get(string &text){
int jjj = 0;
for(int j=text.size()-1; j>=0; --j){
int idx = text[j] - 'a';
if(!vis[idx])vis[idx] = true;
L[idx][jjj] += 1;
L[idx][jjj+1] += (L[idx][jjj]/26);
L[idx][jjj] %= 26;
++jjj;
len[idx] = max(len[idx], jjj);
int iii = jjj;
while(L[idx][iii]>=26){
L[idx][iii+1] += (L[idx][iii]/26);
L[idx][iii] %= 26;
++iii;
}
len[idx] = max(len[idx], iii);
}
}
int Sort(){
int jjj = 0;
for(int i=0; i<30&&vis[i]; ++i){
int lrh = len[i] + 50;
for(int j=len[i]-1; j<lrh; ++j){
L[i][j+1] += L[i][j]/26;
L[i][j] %= 26;
if(L[i][j]!=0) len[i] = j+1;
}
for(int j=len[i]-1; j>=0; --j){
A[jjj].ss += (char)(L[i][j]+'a');
}
A[jjj].idx = i;
++jjj;
}
sort(A, A+jjj);
int tot = 25;
for(int i=0; i<jjj; ++i){
mp[A[i].idx] = 25 - i;
}
int cnt = 0;
for(int i=0; i<26; ++i){
if(vis[i]) ++cnt;
}
if(cnt==26){
tot = 1;
bool flag = true;
for(int i=jjj-1; i>=0; --i){
if(flag && !another_vis[A[i].idx]){
mp[A[i].idx] = 0;
flag = false;
}
else{
mp[A[i].idx] = tot++;
}
}
}
return jjj;
}
long long solve(int vsize){
long long ans = 0;
for(int i=0; i<vsize; ++i){
long long val = mp[A[i].idx];
long long tmp = 0;
long long zhishu = 1;
int lgt = A[i].ss.size();
for(int j=lgt-1; j>=0; --j){
tmp += (((A[i].ss[j]-'a')*val%mod)*zhishu %mod);
zhishu = zhishu*26%mod;
}
ans = (ans + tmp)%mod;
}
return ans;
}
int main(){
Case = 1;
ios::sync_with_stdio(false);
vector<int> v;
while(cin>>n){
init();
for(int i=0; i<n; ++i){
string text;
cin>>text;
v.push_back(text.size());
another_vis[text[0]-'a'] = true;
get(text);
}
cout<<"Case #"<<Case++<<": "<<solve(Sort())<<endl;
}
return 0;