zoukankan      html  css  js  c++  java
  • UVA

    题目大意:

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

    思路:

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

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

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

      那么,将每一个串的每一个字符都看作一个点,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 }
  • 相关阅读:
    实现Oracle的字符串分割(split)[摘录]
    批处理加密[转摘]
    .NET Framework 3.5 SP1安装时下载文件问题及精简方法[转载]
    Oracle 管道化表函数(Pipelined Table)[转载]
    FCKeditor只读与编辑状态切换的不完全解决方案[原创]
    C# Web开发中弹出对话框的函数[转载]
    广发信用卡提现手续费及利息计算器VB源码[原创]
    提升个人网站流量的工具集合(真实IP流量)[转载]
    12.26 3日沙盘Top20分析
    12.29 股票量能沙盘分析软件更新
  • 原文地址:https://www.cnblogs.com/HHshy/p/6159418.html
Copyright © 2011-2022 走看看