给你两个域名,域名中包含一些通配符。
* :匹配一个或任意多个部分
?:匹配一个或三个部分
!:匹配三个以上部分。
求这两个域名是否能够表示同一个域名?
域名的长度不超过255.
分析:设给出的域名为A,B,以f[i][j]表示域名A的前i个部分和域名B的前j个部分是否可能相同。类似于求最长公共子串的转移方式。
f[i][j]=f[i-1][j-1]||f[i][j-1] 如果A[i]是*号。
f[i][j]=f[i-1][j-1]||f[i-1][j-2]||f[i-1][j-3] //如果A[i]是?号,但这么写是有问题的。如果B[j]也是通配符,就错了。
于是我们势必将A[i]和B[j]一起考虑。这里就会有最多16种情况,当然其中有些情况可以合并。
但是仍然有问题。比如A[i]是?号,B[j]是?号。
如果方程这样写:f[i][j]=f[i-1][j-1]||f[i-1][j-2]||f[i-1][j-3]||f[i-2][j-1]||f[i-3][j-1] ,则如果B[j-1]是!号,则有问题。
如果方程这样写:f[i][j]=f[i-1][j-1]||f[i][j-1]||f[i-1][j],则如果f[i][j-1]=1,但此时A[i]已经表示了三个部分了,没办法再表示B[j]了,又怎么办呢?
所以这种转移是很不好办的。
我们感觉到,如果通配符只能表示0个,1个或任意多个是比较好处理的。所以,我们将原有的通配符做一个转换。
*意义不变
?变成只能匹配一个部分
!变成只能匹配0个或1个部分。
则原来的?=?!!(新符号)
原来的!=??*
这样的话,就好处理多了。
先考虑*号,再考虑!号,再考虑?或非通配符。具体转移看代码。
1 #include<iostream> 2 #include<cstdio> 3 #include<sstream> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 int n,cas; 8 #define MAXN 800 9 char s[MAXN][MAXN],t[MAXN][MAXN]; 10 char ss[MAXN],tt[MAXN]; 11 bool f[MAXN][MAXN]; 12 int cnt1=1,cnt2=1,pos=0; 13 int convert(char *ss,char s[][MAXN]) 14 { 15 int cnt=1,pos=0; 16 int slen=strlen(ss); 17 for(int i=0;i<slen;i++) 18 { 19 if(ss[i]!=‘.‘) 20 { 21 if(ss[i]==‘!‘) 22 {s[cnt++][0]=‘?‘; 23 s[cnt++][0]=‘?‘; 24 s[cnt][0]=‘*‘; 25 } 26 else if(ss[i]==‘?‘) 27 { 28 s[cnt++][0]=‘?‘; 29 s[cnt++][0]=‘!‘; 30 s[cnt][0]=‘!‘; 31 } 32 else s[cnt][pos++]=ss[i]; 33 } 34 else 35 cnt++,pos=0; 36 } 37 return cnt; 38 } 39 int main() 40 { 41 scanf("%d\n",&cas); 42 while(cas--) 43 { 44 memset(f,0,sizeof f); 45 memset(s,0,sizeof s); 46 memset(t,0,sizeof t); 47 gets(ss); 48 //cerr<<ss<<endl; 49 gets(tt); 50 //cerr<<tt<<endl; 51 cnt1=convert(ss,s); 52 cnt2=convert(tt,t); 53 f[0][0]=1; 54 for(int i=1;i<=cnt1;i++) 55 for(int j=1;j<=cnt2;j++) 56 { 57 if(s[i][0]==‘*‘) 58 f[i][j]=f[i][j]||f[i][j-1]||f[i-1][j-1]; 59 if(t[j][0]==‘*‘) 60 f[i][j]=f[i][j]||f[i-1][j]||f[i-1][j-1]; 61 62 else if(s[i][0]==‘!‘) 63 f[i][j]=f[i][j]||f[i-1][j]||f[i-1][j-1]; 64 else if(t[j][0]==‘!‘) 65 f[i][j]=f[i][j]||f[i][j-1]||f[i-1][j-1]; 66 else if(s[i][0]==‘?‘||t[j][0]==‘?‘) 67 { 68 f[i][j]=f[i][j]||f[i-1][j-1]; 69 } 70 else if(strcmp(s[i],t[j])==0) 71 f[i][j]=f[i-1][j-1]; 72 } 73 if(f[cnt1][cnt2]==0) 74 printf("NO\n"); 75 else printf("YES\n"); 76 } 77 }
时间: 2024-10-15 18:03:40