General Sultan Input: Standard Input Output: Standard Output |
This is war time again! Our beloved Sultan has assumed the post of a general and going to the war with his huge army. Being an intelligent fellow as he is, he has discovered a handful of new weapons to help him win the war. In order to facilitate instructing his units, he assigns each type of weapon a single binary code. For example, he has three types of weapons -
FordCannon (code: 1)
EdmondMortar (code: 10)
HopcroftRifle (code: 00)
So, now when he makes one long beep and one short beep (that is, 10) from his grand whistle, an EdmondMortar unit is fired while when he makes two short beeps means, 00), a HopcroftRifle comes into action. Please note that, he has an unlimited supply of every types.
Problem arised when in an war, the units were coded like – FordCannon (01), EdmondMortar (001), HopcroftRifle (01001). Once, he went for a HopcroftRifle (01001) but his men fired a FordCannon (01) and then an EdmondMortar (001) instead. The furious Sultan realized that the coding itself was ambigous i.e. more than one sequence of the weapons can translate into the same signal.
Now, your task is to determine if a given coding scheme is ambiguous or not before the war starts.
Input
There will be around 100 test cases. Every test case starts with a single integer N (1≤ N ≤ 100), the number of weapon types. Each of the following N lines contains a string (denoting the name of the weapon, less than 21 characters) and a binary number (the code, less than 21 characters).
The last test case will be followed by a single 0.
Output
For every test case, print “Case #x: ”, where x is the case number. Then print “Ambiguous.” if a code leads to multiple sequences or print “Not ambiguous.” otherwise.
Sample Input Output for Sample Input
3 FordCannon 1 EdmondMortar 10 HopcroftRifle 00 3 FordCannon 01 EdmondMortar 001 HopcroftRifle 01001 0 | Case #1: Not ambiguous. Case #2: Ambiguous. |
题意:给出01串,问能否唯一表示,说例子好懂一些:00,01,0001 这个就有歧义,第三个武器能由前两种组合出来,所以有歧义,还有110,011,11,00 这个也有歧义因为如果是110011表示的也有两种翻译方法。
思路:我想不到正确的办法啊。。。就只能去水一下了,能水过也不错哈!平时如果没想到好办法,就想办法去水一下吧,当然不要用明显会错的方法去水啦。我的办法是,用任意两组组成一个长串,看能不能由短串组合出来,可以的话就有歧义咯,如果不可以就姑且当他可以咯。。。。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 100+5;
char weapon[maxn][25];
char buffer[maxn];
int L;
bool sel[maxn];
bool vis[maxn];
int len[maxn];
int succ[maxn];
int n;
inline int cmp(const void * s1 , const void * s2)
{
int len1 = strlen((char*)s1);
int len2 = strlen((char*)s2);
if (len1 < len2) return 1;
else if (len1 > len2) return -1;
return 0;
}
void input()
{
for (int i = 1 ; i <= n ; ++i) scanf("%*s%s",weapon[i]);
qsort(weapon+1,n,sizeof(weapon[0]),cmp);
for (int i = 1 ; i <= n ; ++i)
len[i] = strlen(weapon[i]);
for (int i = 0 ; i <= len[1]*2 ; ++i)
{
int j;
for (j = 1 ; j <= n ; ++j)
if (len[j] <= i) break;
succ[i] = j;
}
}
bool match(int cur,int pos)
{
for (int i = 0 ; i < len[cur] ; ++i)
if (buffer[pos+i]!=weapon[cur][i]) return false;
return true;
}
bool dfs(int pos,int s,int cur,int sel1,int sel2)
{
if (s==3) return true;
if (pos==L) return false;
for (int i = cur ; i <= n ; ++i) if (match(i,pos))
{
if (sel1==i && !(s&1)) {
if (!dfs(pos+len[i],s+1,succ[L-pos-len[i]],sel1,sel2))
return false;
}
else if (sel2==i && !(s&2)) {
if (!dfs(pos+len[i],s+2,succ[L-pos-len[i]],sel1,sel2))
return false;
}
else if (!dfs(pos+len[i],s,succ[L-pos-len[i]],sel1,sel2))
return false;
}
return true;
}
void solve()
{
for (int i = 1 ; i <= n ; ++i)
{
for (int j = 1 ; j <= n ; ++j)
{
strcpy(buffer,weapon[i]);
strcat(buffer,weapon[j]);
L = len[i]+len[j];
if (!dfs(0,0,succ[L],i,j)) {
cout << " Ambiguous." << endl;
return;
}
}
}
cout << " Not ambiguous." << endl;
}
int main()
{
int Cas = 0;
while (scanf("%d",&n),n)
{
++Cas;
input();
printf("Case #%d:",Cas);
solve();
}
}