Problem C. Concatenation

Input file: concatenation.in
Output file: concatenation.out
Time limit: 2 seconds
Memory limit: 256 megabytes
Famous programmer Gennady likes to create new words. One way to do it is to concatenate existing
words. That means writing one word after another. For example, if he has words “cat” and “dog”, he
would get a word “catdog”, that could mean something like the name of a creature with two heads: one
cat head and one dog head.
Gennady is a bit bored of this way of creating new words, so he has invented another method. He takes
a non-empty prefix of the first word, a non-empty suffix of the second word, and concatenates them. For
example, if he has words “tree” and “heap”, he can get such words as “treap”, “tap”, or “theap”. Who
knows what they could mean?
Gennady chooses two words and wants to know how many different words he can create using his new
method. Of course, being a famous programmer, he has already calculated the answer. Can you do the
same?
Input
Two lines of the input file contain words chosen by Gennady. They have lengths between 1 and 100 000
characters and consist of lowercase English letters only.
Output
Output one integer — the number of different words Gennady can create out of words given in the input
file.
Examples
concatenation.in concatenation.out
cat
dog
9
tree
heap
14
题意:第一个字母从前往后数做前缀,第二个字母从后往前数做后缀,问有几种情况(注意减去重复的)
本题的关键和难点都在于如何去除重复的,想的是重复的很多,假设分块的话会很麻烦,后来也没找到规律,赛后才发现了。
我们找到一个常规重复的
mm
mmm
因为我们找常规的部分,所以设这两段分别在其序列的中间。
因为我们有(2+1)* (3+1)-1种选法(一定要注意两者均可以选0个m但不能同时为0),而去重之后是1,2,3,4,5个m,所以重复的个数是(2+1) * (3+1)-1-(2+3)=6,规律也就自然而然的出来了,设上面连续相同元素的个数为m个,下面连续相同元素相同的个数是n个,则可以选择的方案数为(n+1)*(m+1)-1,而非重复元素的个数(n+m) 所以重复元素的情况为(n+1) * (m+1)-1-(m+n)=nm,我们得到了规律,连续相同字母间重复的个数为nm个。
而在整个字符串中不仅仅有一对相等的,很多对,很多个我们以一个字母为例假设是m吧
s1中:1 4
s2中:3 5 2 (数据分别为s1,s2中的连续m的块数)
可以得出,结果为(1+4) * 3 +(1+4) * 5 + (1+4) * 2 = (1+4) * (3+5+2) 也就是分别为上下两个字符串中的本元素总数量乘积。

本题要注意的是记录数量时第一个字符串的开头,以及第二个字符串的结尾不能记录下去,因为我们发现,1串结尾和2串开头都是必须要选择的,其他相同的原因都是选择有或者是没有的情况,例如样例中tr和eap 以及tre和ap 所以都是选择或不选择地问题,而1开头和2结尾必须选择所以不能记录到数组中。
下面是AC代码:,

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
ll a[30],b[30];
int main()
{
    freopen("concatenation.in", "r", stdin);
    freopen("concatenation.out", "w", stdout);
    string s1;
    string s2;
    cin>>s1;
    cin>>s2;
    ll len1=s1.size(),len2=s2.size();
    for(int i=1;i<len1;i++) a[s1[i]-'a']++;
    for(int i=0;i<len2-1;i++) b[s2[i]-'a']++;
    ll ans=len1*len2;
    for(int i=0;i<=25;i++) ans-=a[i]*b[i];
    printf("%lld\n",ans);
    return 0;
}

在这里要注意的是数组即ans要开long long

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值