UVA - 11604 General Sultan 题解

题目大意:

  有若干模式串,将某些模式串拼接起来(一个可以使用多次)形成一个长模式串,判断能否有两种或更多种不同的拼法拼成相同的模式串。

思路:

  神奇的构图,暴力的求解。

  可以发现,若有不同的拼法,则一个模式串的前缀要与一个模式串的后缀相同。

  因此我们就将问题转化成:从两个模式串开始,不停的按照前后缀匹配,最后达到两个串同时在一个点结束。

  那么,将每一个串的每一个字符都看作一个点,n2len2暴力枚举i串从z开始的后缀和j串(自己也可以,但不能让前缀是其本身)的前缀做匹配,看是否能将其中一个串匹配完。

  当(i,z)和j匹配,若i先结束了,则将(i,z)这个点连边到j串没匹配的第一个点,表示下一次匹配应该是从j的那个位置开始当后缀再寻找其他前缀;如果j先结束,与之前一个类似;如果i和j同时结束,则连边到终点。

  最后用dfs判断能否从某个模式串的第一个点开始走到终点。

  PS:1、fromhttp://blog.csdn.net/houserabbit/article/details/38943645

     2、数组的意义、范围要清楚,我花了一个多小时才发现数组开小了。

代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 using namespace std;
 4 const int M=109,N=30;
 5 int n,e,t,i,j,k,z,cnt,v[M*M*N*N],id[M][N],nex[M*M*N*N],len[M],head[M*N];
 6 bool vis[M*N],flag;
 7 char s[M][N];
 8 
 9 void add(int x,int y) { v[++cnt]=y,nex[cnt]=head[x],head[x]=cnt; }
10 
11 void dfs(int x)
12 {
13     if (x==e) { flag=1; return; }
14     vis[x]=1;
15     for (int i=head[x];~i;i=nex[i])
16         if (!vis[v[i]])
17         {
18             dfs(v[i]);
19             if (flag) return;
20         }
21 }
22 
23 int main()
24 {
25     while (~scanf("%d",&n))
26     {
27         if (!n) break;
28         e=cnt=flag=0;
29         for (i=1;i<=n;++i)
30         {
31             scanf("%s%s",s[i],s[i]);
32             len[i]=strlen(s[i]);
33             for (j=0;j<len[i];++j) id[i][j]=++e;
34         }
35         for (++e,i=0;i<=e;++i) head[i]=-1;
36         for (i=1;i<=n;++i)
37             for (z=0;z<len[i];++z)
38                 for (j=1;j<=n;++j)
39                 {
40                     if (i==j && !z) continue;
41                     for (k=0;k<len[j] && z+k<len[i];++k)
42                         if (s[i][z+k]!=s[j][k]) break;
43                     if (z+k==len[i] && k==len[j]) add(id[i][z],e);
44                     else if (k==len[j]) add(id[i][z],id[i][z+k]);
45                          else if (z+k==len[i]) add(id[i][z],id[j][k]);
46                 }
47         for (i=0;i<=e;++i) vis[i]=0;
48         for (i=1;i<=n;++i)
49         {
50             if (!vis[id[i][0]]) dfs(id[i][0]);
51             if (flag) break;
52         }
53         printf("Case #%d: ",++t);
54         if (flag) puts("Ambiguous."); else puts("Not ambiguous.");
55     }
56     return 0;
57 }

 

posted @ 2016-12-11 12:41  HHshy  阅读(481)  评论(0编辑  收藏  举报