【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网址
- 1272 小希的迷宫
- 1272 小希的迷宫
- hdu 1250 大数相加并用数组储存
- 矩阵的乘法操作
- 蚂蚁爬行问题
- 蚂蚁爬行问题
- 求两个数的最大公约数【ACM基础题】
- 打印出二进制中所有1的位置
- 杭电题目---一只小蜜蜂
- HDOJ 1002 A + B Problem II (Big Numbers Addition)
- 初学ACM - 半数集(Half Set)问题 NOJ 1010 / FOJ 1207
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1002
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points