codeforces 922 D Robot Vacuum Cleaner

Description

Pushok the dog has been chasing Imp for a few hours already.

Imp

Fortunately, Imp knows that Pushok is afraid of a robot vacuum cleaner.

While moving, the robot generates a string t consisting of letters ‘s’ and ‘h’, that produces a lot of noise. We define noise of string t as the number of occurrences of string “sh” as a subsequence in it, in other words, the number of such pairs (i,j) , that i  < j and ti=s and tj=h .

The robot is off at the moment. Imp knows that it has a sequence of strings ti in its memory, and he can arbitrary change their order. When the robot is started, it generates the string t as a concatenation of these strings in the given order. The noise of the resulting string equals the noise of this concatenation.

Help Imp to find the maximum noise he can achieve by changing the order of the strings.

Input

The first line contains a single integer n (1 ≤ n ≤ 10 5 ) — the number of strings in robot’s memory.

Next n lines contain the strings t1,t2,...,tn , one per line. It is guaranteed that the strings are non-empty, contain only English letters ‘s’ and ‘h’ and their total length does not exceed 10 5 .

Output

Print a single integer — the maxumum possible noise Imp can achieve by changing the order of the strings.

Examples

Input
4
ssh
hs
s
hhhs
Output
18
Input
2
h
s
Output
1

Note

The optimal concatenation in the first sample is ssshhshhhs.


题意:给n个只包含‘s’和‘h’的字符串,调整他们的顺序,使拼起来的串含有最多的以‘s’开头以‘h’结尾的字串。
思路:首先考虑子串数目的计算对于两个字符串 t1 t2 。对于每个给定的字符串,其内部顺序是不可以改变的,因此记录它含有的s,h,和内部sh字串的数目就已经包含计算子串所需要的全部信息了,不妨抽象为一个数据结构

struct{
    int cnts;//含有的s数量
    int cnth;//含有的h数量
    int ns;//内部sh子串数量
};

容易计算出连接 t1 - t2 形成的串有的子串数量为 t1 .ns + t2 .ns + t1 .cnts × t2 .cnth。在寻找最大子串数量的过程中, t1 .ns 和 t2 .ns无论怎么摆放都不变,调整顺序只改变了用哪些字符串的cnts来乘哪些字符串的cnth,因此可以给这个数据结构定义一个先后关系,如果 t1 .cnts × t2 .cnth > t2 .cnts × t1 .cnth ,那么就认为 t1 应该排在 t2 前面,如果两个乘积相同,就应该把含‘s’更多的字符串放在前面。有了这个关系,就可以用sort函数来排序啦,最后的计算也比较容易,应该注意到一点是,s和h的数量可以达到几万,相乘的结果用int保存可能会溢出

#include <stdio.h>
#include<algorithm>
using std::sort;
struct sh
{
    unsigned long cnts;
    unsigned long cnth;
    int ns;
    sh():cnts(0),cnth(0),ns(0) {}
}str[100005];

bool cmp(sh a, sh b) {
    unsigned long tempa = a.cnts*b.cnth;//用unsigned long 暂存结果
    unsigned long tempb = a.cnth*b.cnts;
    if (tempa >tempb)return true;
    else if (tempa < tempb)return false;
    else {//“相等”的情况
        //把含's'更多的字符串放在前面,能与其他字符串生成更多的sh子串
        if (a.cnts > b.cnts)
        return true;
        if (a.cnts < b.cnts)return false;
        else {
            return a.cnth < b.cnth;
        }
    }

} 
char d;


int main() {
    int n;
    long long  ans=0, ts=0, th=0;
    scanf("%d", &n);
    scanf("%c", &d);//额外的换行符

    for (int i = 0; i < n;++i) {
        while (1)
        {
            scanf("%c", &d);
            if (d == 's')str[i].cnts++;
            else if (d == 'h') { str[i].cnth++; str[i].ns += str[i].cnts; }
            else break;//读取到回车,一个输入结束
        }
    }
    sort(str, str + n, cmp);//按我们定义的先后关系排序
    //最后的计算,用ts记录当前位置前面已经有多少个s
    for (int i = 0; i < n; ++i) {
        //加上这个字符串的内部sh子串数
        ans += str[i].ns;
        //这个字符串与前面的所有的字符串产生sh子串数
        ans += ts*str[i].cnth;
        //更新ts
        ts += str[i].cnts;
    }

     printf("%I64d\n", ans);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值