【Uva 11604 编码都有歧义了】

·你的目的就是要让编码有歧义,这就美妙了。

·英文题,述大意:

      给出n个模板字符串,询问是否存在一个字符串,使得用模板串(随便你用多少个)来拼凑这个串,能够至少有两种拼法。如果有,就输出“有”。

·分析:

     值得注意的是,n的范围不太大(0<n<101)。

     如果直接思考如何拼凑,那么就是一个典型的搜索枚举思想,对于这道题来说,也是一个典型的爆炸超时思想。不过,如果拥有一个好的习惯,你会不禁想到:正着不行反着来。所以,我们考虑对于一个串,把它切成几块,并使得每块都属于模板串。如果有两种切法,那么就可以输出“Yes”了。

比如这样:

·目的明确。对于一个串,我们将其切割,我们在将这样的状态重画一遍:

·玩着玩着,我们意识到:分成的小段一定是属于模板串的。所以考虑用模板串去填出大串(逆向思维已经贡献了它的全部加值,现在应该回来了)。

·分析一类简单情况,如图,我们要拼凑满足条件的大串:

·首先会拿上面两个模板串,就拼出了大串。然后你会拿下面两个模板串再来拼一个一样的大串,然后就可以输出“Yes”了。

·在反复拼凑的过程中,得到一些结论:
①每种拼法每一个位置上的字母上一样的(不要忽视)

②不同的拼法,所使用模板串时,发现只有部分重叠(相同)的模板串能够在靠近的位置,如图:

·可以看见,红串绿串有公共前缀,在不同拼法中起点相同;黄串与蓝串有公共后缀,在不同拼法中终点相同;红串与黄串的关系是:红串的一个后缀等于黄串的一个前缀,它们在不同拼法中收尾相接(部分重叠)。你可以在冥冥之中感受到,两种拼凑方式是有联系的,即这个串可能会“指导”另一个串的合成。

·神秘跳跳方法解决问题。我们用这样的顺序,来搭建这两个串:(结合上图吧)先在上面放置一个绿串,然后在模板中寻找前缀与它相同的串来搭建下面的串,于是找到了红串,将红串放置。现在红串伸出去了一截,在模板中寻找前缀与这一截相同的串,找到黄串,放在上面。现在黄串伸出去了一截,在模板串中寻找前缀与这一截相同的串,找到蓝串,放置蓝串于下方。发现没有那个伸出去一截了,也就是说,当前拼的大串,我们已经找到有两种拼法了。

·总结规律:只要还伸出去了一截,我们就永不停息,直到没有伸出的一截。说句老实话,找不到就是找不到,还是要停息的(不停息的现实意义就是超时)。

·方法:枚举两两模板串,并记录一个模板串的第i位开始,可以接上(即上文的相同)另一个串的开头(举例子就是红串的第6位开始可以接上黄串)。怎样表示关系呢?就建边把,将每一个模板串的每一位看成一个节点,然后就搭建有向边(比如红串第6位可一建一条边通向黄串第5位)。什么时候结束呢,如果从某个串i位到末尾就完全等于一个另一个模板串(就像上文黄串与蓝串的关系一样),就说明不会冒出一截了,也就是找到答案。

·代码(防水的)浮出水面:

 1 #include<stdio.h>
 2 #include<cstring>
 3 #define go(i,a,b) for(int i=a;i<=b;i++)
 4 #define fo(i,a,x) for(int i=a[x],v=e[i].v;i;i=e[i].next,v=e[i].v)
 5 const int N=110;struct E{int v,next;}e[N*300];
 6 int T,x,n,m,len[N],sz,ID[N][30],head[N*30],k,over;char s[N][30];bool vis[N*30],can;
 7 void ADD(int u,int v){e[k]=(E){v,head[u]};head[u]=k++;}
 8 void dfs(int u){if(can=u==over)return;vis[u]=1;fo(i,head,u)if(!vis[v]){dfs(v);if(can)return;}}
 9 int main(){while(scanf("%d",&x),can=sz=0,k=1,x)
10 {
11     go(i,1,x){scanf("%s%s",s[i]+1,s[i]+1);len[i]=strlen(s[i]+1);
12     go(j,1,len[i])vis[sz]=head[ID[i][j]=++sz]=0;}vis[sz+1]=0;
13
14     go(a,1,x){n=len[a];go(I,1,n){go(b,1,x){m=len[b];
15         if(a==b&&I==1)continue;int i=I-1,j=0;
16         while(s[a][++i]==s[b][++j]&&i<=n&&j<=m);
17         if(i>n&&j>m) ADD(ID[a][I],over);
18         if(i<=n&&j>m)ADD(ID[a][I],ID[a][i]);
19         if(i>n&&j<=m)ADD(ID[a][I],ID[b][j]);
20     }}}
21     go(i,1,x){if(!vis[ID[i][1]])dfs(ID[i][1]);if(can)break;}
22     printf("Case #%d: ",++T);puts(can?"Ambiguous.":"Not ambiguous.");
23 }return 0;}//Paul_Guderian

我无法忘记故乡秋末的麦地,
和南方水柳摇摆的倩影。——————汪峰《雨天的回忆》

时间: 2024-12-12 04:45:26

【Uva 11604 编码都有歧义了】的相关文章

UVA - 11604 General Sultan(构图暴力)

题目大意:给出n个字符串(01串),问是否存在一个二进制序列,存在至少两种编码方式 比如{a = 01011111, b = 0101, c = 1111010, d = 010} 二进制序列01011111010就有两种编码方式了,可以由a+d组成,也可以由b+c+d组成(注意这里的二进制序列不是指所给的武器的二进制序列,刚开始没理解..被坑了) 解题思路:这样就比较好理解了,字符串匹配,不断的匹配 首先为每个字符都构建一个点,那怎么连边呢? 找匹配的部分进行连边,假设有两个字符串i,j,现在

UVA - 11604 General Sultan 题解

题目大意: 有若干模式串,将某些模式串拼接起来(一个可以使用多次)形成一个长模式串,判断能否有两种或更多种不同的拼法拼成相同的模式串. 思路: 神奇的构图,暴力的求解. 可以发现,若有不同的拼法,则一个模式串的前缀要与一个模式串的后缀相同. 因此我们就将问题转化成:从两个模式串开始,不停的按照前后缀匹配,最后达到两个串同时在一个点结束. 那么,将每一个串的每一个字符都看作一个点,n2len2暴力枚举i串从z开始的后缀和j串(自己也可以,但不能让前缀是其本身)的前缀做匹配,看是否能将其中一个串匹配

为什么写注释必须成为编码的硬性标准(双语原创)

为什么写注释必须成为编码的硬性标准(双语原创) Why Writing Annotation Must Become Peremptory Rule? 程序猿最烦的事:别人的代码不写注释:自己写注释. Parodox: It is most hated for programmers that others'code have not annotations, and oneself must write annotations. 1.注释最主要是给别人看的,供自己回顾是锦上添花 理解一个人的思

UVA 322 ships (POJ 1138)

题目地址: http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=258 http://poj.org/problem?id=1138 题目描写叙述:  Ships  Probably everyone who ever attended school knows the game where two opposing players place

Python2.7字符编码详解

一. 字符编码基础 为明确概念,将字符集的编码模型分为以下4个层次: 抽象字符清单(Abstract Character Repertoire, ACR):待编码文字和符号的无序集合,包括各国文字.标点.图形符号.数字等. 已编码字符集(Coded Character Set, CCS):从抽象字符清单到非负整数码点(code point)集合的映射. 字符编码格式(Character Encoding Form, CEF):从码点集合到指定宽度(如32比特整数)编码单元(code unit)的

RFID 基础/分类/编码/调制/传输

不同频段的RFID产品会有不同的特性,本文详细介绍了无源的感应器在不同工作频率产品的特性以及主要的应用. 目前定义RFID产品的工作频率有低频.高频和甚高频的频率范围内的符合不同标准的不同的产品,而且不同频段的RFID产品会有不同的特性. 其中感应器有无源和有源两种方式,下面详细介绍无源的感应器在不同工作频率产品的特性以及主要的应用. 1. 低频(从125KHz到134KHz)   其实RFID技术首先在低频得到广泛的应用和推广.该频率主要是通过电感耦合的方式进行工作, 也就是在读写器线圈和感应

【转】关于字符编码,你所需要知道的(ASCII,Unicode,Utf-8,GB2312…)

转载地址:http://www.imkevinyang.com/2010/06/%E5%85%B3%E4%BA%8E%E5%AD%97%E7%AC%A6%E7%BC%96%E7%A0%81%EF%BC%8C%E4%BD%A0%E6%89%80%E9%9C%80%E8%A6%81%E7%9F%A5%E9%81%93%E7%9A%84.html 字符编码的问题看似很小,经常被技术人员忽视,但是很容易导致一些莫名其妙的问题.这里总结了一下字符编码的一些普及性的知识,希望对大家有所帮助. 还是得从ASC

[转]ASCII UNICODE与UTF-8编码规则及区别

字符编码是计算机技术的基石,想要熟练使用计算机,就必须懂得一点字符编码的知识. 1. ASCII码 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的字符串.每一个二进制位(bit)有0和1两种状态,因此八个二进制位就可以组合出 256种状态,这被称为一个字节(byte).也就是说,一个字节一共可以用来表示256种不同的状态,每一个状态对应一个符号,就是256个符号,从 0000000到11111111. 上个世纪60年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一

关于字符编码,你所需要知道的(ASCII,Unicode,Utf-8,GB2312…)

字符编码的问题看似很小,经常被技术人员忽视,但是很容易导致一些莫名其妙的问题.这里总结了一下字符编码的一些普及性的知识,希望对大家有所帮助. 还是得从ASCII码说起 说到字符编码,不得不说ASCII码的简史.计算机一开始发明的时候是用来解决数字计算的问题,后来人们发现,计算机还可以做更多的事,例如文本处 理.但由于计算机只识“数”,因此人们必须告诉计算机哪个数字来代表哪个特定字符,例如65代表字母‘A’,66代表字母‘B’,以此类推.但是计算机之间字符-数字的对应关系必须得一致,否则就会造成同