POJ 1229 Wild Domains 动态规划

POJ 1229 Wild Domains 动态规划

这题看上去很冷门~
其实也是的,第一眼看上去想不到好的解法,但是将问题稍稍转化一下就很好办了。

思路:
两个pattern匹配的过程,如果没有通配符,那就是从左到右,逐个逐个的匹配。
由于存在通配符,a的一个节点有可能匹配b的数个节点,同样,b的一个节点也有可能匹配a的数个节点。
这就需要搜索了。但是一开始发现搜索的时候通配符的处理真的很麻烦。感觉就是代码稍微写错一点就会WA。

于是想简化一下问题。重新定义三种通配符:
ONE   匹配一个单词
ZERO_ONE  匹配零个或一个单词
ANY 可以匹配零个或多个单词

这样:
* = ONE, ANY
? = ONE, ZERO_ONE, ZERO_ONE
! = ONE, ONE, ONE, ANY

这样做的好处是,避免了考虑通配符匹配的单词数目。
规划的时候处理 ONE, ZERO_ONE, ANY 是很简单的。
f[a][b] = { 第一个pattern从a处开始匹配,第二个pattern从b处开始匹配,匹配成功则为1,否则为0 }
转移的时候:
f[a][b] = {
pattern[1][a]为ANY的时候 = f[a + 1][b] || f[a][b + 1] || f[a + 1][b + 1]
pattern[1][a] 为ONE的时候 = {
      pattern[2][b] 为 ONE 的时候 = f[a + 1][b + 1]
      pattern[2][b] 为 ZERO_ONE 的时候 = f[a][b + 1] || f[a + 1][b + 1]
      ....
      }
.....
}

#include  < stdio.h >
#include 
< string .h >

struct  _in  {
    
char *arr[256], line[256];
    
int cnt;
}
  in [ 2 ];

enum  _node_type  {
    ZERO_ONE, ONE, ANY, STR, END
}
;
struct  _node  {
    
enum _node_type type;
    
char *str;
}
 stk[ 2 ][ 512 ];

int  dp[ 512 ][ 512 ], tm;

void  input( struct  _in  * t)
{
    
int i;

    scanf(
"%s", t->line);
    
for (i = t->cnt = 0; ; i++{
        t
->arr[t->cnt++= &t->line[i];
        
while (t->line[i] && t->line[i] != '.')
            i
++;
        
if (!t->line[i])
            
break;
        t
->line[i] = 0;
    }

}


void  init( struct  _in  * t,  struct  _node  * s)
{
    
int i;

    
for (i = 0; i < t->cnt; i++{
        
switch (*t->arr[i]) {
        
case '*':
            s
->type = ONE; s++;
            s
->type = ANY; s++;
            
break;
        
case '?':
            s
->type = ONE; s++;
            s
->type = ZERO_ONE; s++;
            s
->type = ZERO_ONE; s++;
            
break;
        
case '!':
            s
->type = ONE; s++;
            s
->type = ONE; s++;
            s
->type = ONE; s++;
            s
->type = ANY; s++;
            
break;
        
default:
            s
->type = STR;
            s
->str = t->arr[i];
            s
++;
            
break;
        }

    }

    s
->type = END;
}


int  visited( struct  _node  * a,  struct  _node  * b)
{
    
struct _node *t;

    
if (a > b) {
        t 
= a;
        a 
= b;
        b 
= t;
    }


    
return dp[a - stk[0]][b - stk[1]] == tm;
}


void  set_visited( struct  _node  * a,  struct  _node  * b)
{
    
struct _node *t;

    
if (a > b) {
        t 
= a;
        a 
= b;
        b 
= t;
    }


    dp[a 
- stk[0]][b - stk[1]] = tm;
}


int  match( struct  _node  * a,  struct  _node  * b)
{
    
int r = -1;

    
if (visited(a, b))
        
return 0;

    
if (a->type == ONE) {
        
if (b->type == ONE)
            r 
= match(a + 1, b + 1);
        
if (b->type == ZERO_ONE)
            r 
= match(a, b + 1|| match(a + 1, b + 1);
        
if (b->type == ANY) 
            r 
= match(a, b + 1|| match(a + 1, b + 1|| match(a + 1, b);
        
if (b->type == STR)
            r 
= match(a + 1, b + 1);
        
if (b->type == END)
            r 
= 0;
    }


    
if (a->type == ZERO_ONE) {
        
if (b->type == ZERO_ONE)
            r 
= match(a + 1, b) || match(a, b + 1|| match(a + 1, b + 1);
        
if (b->type == ANY)
            r 
= match(a + 1, b) || match(a, b + 1|| match(a + 1, b + 1);
        
if (b->type == STR) 
            r 
= match(a + 1, b + 1);
        
if (b->type == END)
            r 
= match(a + 1, b);
    }


    
if (a->type == ANY) {
        
if (b->type == ANY)
            r 
= match(a + 1, b) || match(a, b + 1|| match(a + 1, b + 1);
        
if (b->type == STR)
            r 
= match(a + 1, b) || match(a, b + 1|| match(a + 1, b + 1);
        
if (b->type == END)
            r 
= match(a + 1, b);
    }


    
if (a->type == STR) {
        
if (b->type == STR)
            r 
= !strcmp(a->str, b->str) ? match(a + 1, b + 1) : 0;
        
if (b->type == END)
            r 
= 0;
    }


    
if (a->type == END) {
        
if (b->type == END)
            r 
= 1;
    }


    
if (r == -1)
        r 
= match(b, a);

    
if (!r)
        set_visited(a, b);

    
return r;
}


int  main()
{
    
int t;

    scanf(
"%d"&t);
    
while (t--{
        input(
&in[0]);
        input(
&in[1]);
        init(
&in[0], stk[0]);
        init(
&in[1], stk[1]);
        tm
++;
        printf(
"%s\n", match(stk[0], stk[1]) ? "YES" : "NO");
    }

    
    
return 0;
}


 

你可能感兴趣的:(POJ 1229 Wild Domains 动态规划)