您的位置:首页 > 其它

【2015-2016 ACM-ICPC, NEERC, Northern Subregional Contest C】【脑洞 本质不同实现的转化】Concatenation A串为前缀B串为后缀不同串

2015-11-15 20:44 381 查看
#include<stdio.h>
#include<string.h>
#define MS(x,y) memset(x,y,sizeof(x))
typedef long long LL;
const int N=1e5+10,M=0,Z=1e9+7,ms63=1061109567;
char a
,b
;
int c[128];
void fre()
{
freopen("concatenation.in","r",stdin);
freopen("concatenation.out","w",stdout);
}
int main()
{
fre();
while(~scanf("%s%s",a,b))
{
int n=strlen(a);
int m=strlen(b);
MS(c,0);LL ans=LL(n)*m;
for(int i=1;i<n;i++)++c[a[i]];
for(int i=0;i<m-1;i++)ans-=c[b[i]];
printf("%lld\n",ans);
}
return 0;
}
/*
【trick&&吐槽】
一些题目看起来很难,然而却又积极惊人的性质,可以用很高效的复杂度AC >_<
其实一开始就想到了正解,如果抓住问题多思考,就能解决了,好可惜。

【题意】
给你两个串a、b,(长度都为[1,1e5]范围)。
让你从a串取一个非空前缀串,从b串取一个非空后缀串。
然后把两个串拼起来。问你能拼出多少个本质不同串。

【类型】
脑洞

【分析】
在没有重复串的情况下,本质不同串的个数是n*m,
我们怎么考虑本质相同串呢?
想一想这道题可以怎么把问题转化为数学语言——
这题其实就是,我们枚举a串的结尾节点i∈[0~n-1],枚举b串的开头节点j∈[0~n-1],然后两串合并,看是否重复。
什么时候可能出现串重复呢?对于一个a[i]==b[j],我们可以——
1,以a[i]为结尾,抛弃b[j],不以b[j]为开头
2,不以a[i]为结尾,抛弃a[i],以b[j]为开头,
这两者形成的串是相同的,必然会出现本质不同串的个数+1。

然而这个理解起来有些困难,于是我们拿出一组数据{aaa,aaa},
我们发现会形成{a aaa} {aa aa} {aaa a},共计3个aaaa
而两个串什么时候会重复呢?
对于同一个长度的串,当{第一个串延展长度+1,第二个串延展长度-1}且延展后与延展前串相同时,会产生重复串。
实际上,这个产生重复串的条件,等同于a[i]==b[j]。
于是才有了一开始的做法。
现在也给出了具体的证明。
于是可以用O(n)的时间AC啦。

【时间复杂度&&优化】
O(n)

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  ACM codeforces 脑洞