看到这道题时我的内心是奔溃的,没有了解过HTML,只能靠窝的渣渣英语一点一点翻译啊TT、
Information Extraction
题意:(纯手工翻译,有些用词可能在html中不是一样的,还多包涵)
从HTML文档中提取信息,用一种特殊的格式输出。
HTML文件的定义如下:
HTML:
是一种超文本标记语言。标记语言是由一系列的标记组成的。
标签描述文档内容。HTML文件由标签和文本组成。
标签:
HTML使用标签来实现他的语法。
标签由特殊的字符(如: ‘<’, ‘>’ and ‘/’)组成。
标签通常成对出现,起始标签和结束标签。起始标签以<开头,>结尾。
结束标签以</开头,以>结尾。文件的其他地方不会出现尖括号。
标签名是只含有小写字母的字符串。标签中没有行中断。
除了标签,文件中出现的其他东西都被认为是文本内容。
标签名的长度不超过30.
元素:
元素是起始标签和相对应的终止标签之间的任何内容,包括标签在内。
元素内容是开始标签和结束标签之间的内容。
有些元素没有内容,我们叫它空元素,如 <hr></hr>。
空元素可以被关在一个打开标签内,以/>结尾,而不是>。
所有元素都可以被关闭用关闭标签或者在开始标签里面。
元素可以有属性。
元素可以被嵌套,即一个元素可以包含另一个元素。
<html>元素师其他所有元素的容器,他不包含任何属性。
属性:
属性为元素提供额外信息。
属性总是在开始标签中被规定,在标签名的后面。
标签名和属性由一个空格隔开。
一个元素可以有多个属性。
属性以这样的形式出现:name="value" class="icpc",等号两边没有空格。
所有的属性名都是小写的。
id属性的值是唯一的,长度小于等于30.
题目中还给了几个例子,我们来看一下:
sample 1:
<html><body> //<html>是总容器,<body>是标签
<h3 id="header" class="style1">this is a test</h3> //<h3 id="header" class="style1">是起始标签,标签名是h3,有两个属性,id和class。“this is a test”是元素。</h3>是结束标签。
<div id="content" class="style2"> //<div> 标签,同上。
this is content<br/>
<pre>var x = 1111; </pre>
</div>
</body></html> //结束标签
由结构到输出格式的映射如下:
id属性的值-输出格式的标签名
输入:
T:代表有几组样例。
每一个样例都在前面规定它的输出格式。
n:有几种html文件
每一种类型的l结构在之前的html文件中
m: 有几种映射从结构到输出结果
m行映射
最后是html测试案例
输出:
每一组样例,第一行输出“Case #x”
如果存在这种结构的html文件,按格式输出,否则,输出“Can't Identify”如果有多种结构,使用最早输入的结构。
下面我们来分析一样题目给出的测试数据:
input:
2 <news> <title>default title</title> <content width="1000px"></content> </news> 1 <html><h3 id="header"></h3> <div id="content"></div></html> 2 header-title content-content <html><h3 id="header" class="style1"> this is a test</h3> <div id="content" class="style2"> this is content<br/> <pre>var x = 1111;</pre> </div> </html> <xxx> <title>default title</title> </xxx> 1 <html><h3 id="header"></h3></html> 1 header-title <html><h3 id="tmp">xxxx</h3></html>
output:
Case #1: <news> <title> this is a test</title> <content width="1000px"> this is content<br/> <pre>var x = 1111;</pre> </content> </news>
Case #2: Can't Identify
输入分析:
蓝色部分规定了输出格式,绿色部分规定了html文件的结构,红色部分为m种映射,紫色部分是需要提取信息的文本。
拿case 1 来看,<html><h3 id="header" class="style1"> this is a test</h3> <div id="content" class="style2"> this is content<br/> <pre>var x = 1111;</pre> </div> </html> 从中我们可以得出的信息为 标签h3,它的属性id的值为header,上述header的映射为title,所以用标签为title 的格式输出“<title> this is a test</title>” 接下来是div标签,它的属性id的值为content,上述content的映射为content,所以用标签为content的格式输出“ <content width="1000px"> this is content<br/> <pre>var x = 1111;</pre> </content>”,在前后分别加上<news></news>;
case 2:找不到属性值为tmp的映射,所以不能定义。
题意,样例都说完了,下面来看看代码吧(不是本人写的):
1 #include<iostream> 2 #include<cstdio> 3 #include<string.h> 4 using namespace std; 5 const int N=10010; 6 const int M=35; 7 char html[M][N],stored[M][N],sta1[N][M]; 8 char mapping[M][M][2][M];//存储映射情况 9 int mapNum[M],sta2[N]; 10 void getHtmlFormat(int n)//读取html的格式 11 { 12 int j,i=0,flag=1; 13 char beginTag[M];//存储开始标签 14 char tag[M];//存储标签 15 getchar(); 16 while(1) 17 { 18 html[n][i]=getchar();//读取第n个html 19 if(html[n][i]=='<') 20 { 21 j=0; 22 while(html[n][++i]=getchar()) 23 { 24 if(html[n][i]=='/') 25 continue; 26 if(html[n][i]==' '||html[n][i]=='>') 27 break; 28 tag[j++]=html[n][i]; 29 } 30 tag[j]='\0'; 31 if(flag==1) 32 { 33 strcpy(beginTag,tag); 34 flag=0; 35 } 36 else if(!strcmp(tag,beginTag))//表示读到结束标签,读取结束 37 { 38 html[n][++i]='\0'; 39 return; 40 } 41 } 42 i++; 43 } 44 } 45 void getMapping(int n,int m) 46 { 47 int i,j; 48 char mp[100]; 49 cin>>mp; 50 for(i=0; mp[i]!='-'; i++) 51 mapping[n][m][0][i]=mp[i]; 52 mapping[n][m][0][i]='\0'; 53 for(j=0,i++; i<strlen(mp); i++,j++) 54 mapping[n][m][1][j]=mp[i]; 55 mapping[n][m][1][j]='\0'; 56 } 57 void getTag(int n,int i,char tag[]) 58 { 59 int j=0; 60 while(1) 61 { 62 i++; 63 if(html[n][i]=='/') 64 continue; 65 if(html[n][i]==' '||html[n][i]=='>') 66 break; 67 tag[j++]=html[n][i]; 68 } 69 tag[j]='\0'; 70 } 71 int getId(int n,int i,char id[]) 72 { 73 int j; 74 id[0]='\0'; 75 char tmp[M]; 76 while(html[n][i]==' ') 77 { 78 j=0; 79 while(html[n][++i]!='=') 80 tmp[j++]=html[n][i]; 81 tmp[j]='\0'; 82 if(!strcmp(tmp,"id")) 83 { 84 i++; 85 j=0; 86 while(html[n][++i]!='"') 87 id[j++]=html[n][i]; 88 id[j]='\0'; 89 } 90 else 91 { 92 i++; 93 while(html[n][++i]!='"'); 94 } 95 i++; 96 } 97 return i; 98 } 99 void store(int n,int i,int j,char tag[]) 100 { 101 stored[j][0]='\0'; 102 int k,y=0,flag=0,len=strlen(tag); 103 for(i++;; i++) 104 { 105 k=0; 106 if(html[n][i]=='<') 107 for(; k<len; k++) 108 if(tag[k]!=html[n][i+1+k])break; 109 if(k==len)flag++; 110 k=0; 111 if(html[n][i]=='<'&&html[n][i+1]=='/') 112 for(; k<len; k++) 113 if(tag[k]!=html[n][i+2+k])break; 114 if(k==len) 115 { 116 if(!flag) 117 { 118 stored[j][y]='\0'; 119 return; 120 } 121 else flag--; 122 } 123 stored[j][y++]=html[n][i]; 124 } 125 } 126 bool isStructure(int n,int m) 127 { 128 int i,j,k,ii,flag=0,top=-1; 129 char tag[M],id[M],tag2[M],id2[M]; 130 int len1=strlen(html[n]); 131 for(i=k=0; i<len1;) 132 { 133 ii=i; 134 while(html[n][i]==' '||html[n][i]=='\n') 135 i++; 136 while(html[m][k]!='<') 137 k++; 138 getTag(n,i,tag);//获取标签 139 getTag(m,k,tag2); 140 if(strcmp(tag,tag2)||html[n][i+1]!=html[m][k+1]) 141 { 142 if(!strcmp(tag,tag2)) 143 sta2[top]++; 144 if(!flag) 145 { 146 return false; 147 } 148 while(html[m][k]!='>') 149 k++; 150 i=ii; 151 continue; 152 } 153 if(html[n][i+1]=='/') //</xx> 154 { 155 if(!sta2[top]) 156 { 157 i+=strlen(tag)+3; 158 flag--; 159 } 160 else sta2[top]--; 161 k+=strlen(tag)+3; 162 } 163 else //<xx>或者<xx/> 164 { 165 i+=strlen(tag)+1; 166 k+=strlen(tag2)+1; 167 if(html[n][i]==' ') //有id 168 { 169 if(html[m][k]!=' ') 170 { 171 if(!flag) 172 { 173 return false; 174 } 175 while(html[m][k]!='>')k++; 176 i=ii; 177 continue; 178 } 179 i=getId(n,i,id); 180 k=getId(m,k,id2); 181 if(strcmp(id,id2)) 182 { 183 if(!flag) 184 { 185 return false; 186 } 187 while(html[m][k]!='>')k++; 188 i=ii; 189 continue; 190 } 191 } 192 for(j=0; j<mapNum[n]; j++) 193 if(!strcmp(id,mapping[n][j][0])) 194 break; 195 if(html[n][i]=='/') //<xx/> 196 { 197 i+=2; 198 k+=2; 199 } 200 else //<xx> 201 { 202 if(j!=mapNum[n]) //需映射的id 203 { 204 strcpy(sta1[++top],tag); 205 flag++; 206 sta2[top]=0; 207 for(j=0; j<mapNum[n]; j++) 208 if(!strcmp(id,mapping[n][j][0])) 209 store(m,k,j,tag); 210 } 211 i++; 212 k++; 213 } 214 } 215 } 216 return true; 217 } 218 void output(int n) 219 { 220 int i,j,k,ii; 221 char tag[M]; 222 int len1=strlen(html[0]); 223 for(i=0; i<len1;) 224 { 225 while(i<len1&&html[0][i]!='<') 226 putchar(html[0][i++]); 227 if(i==len1)break; 228 getTag(0,i,tag); 229 for(j=0; j<mapNum[n]; j++) 230 if(!strcmp(tag,mapping[n][j][1])) 231 break; 232 if(j==mapNum[n]) 233 { 234 putchar(html[0][i++]); 235 continue; 236 } 237 else 238 { 239 int len=strlen(tag); 240 ii=i; 241 for(i+=len+1;; i++) 242 { 243 k=0; 244 if(html[0][i]=='<'&&html[0][i+1]=='/') 245 for(; k<len; k++) 246 if(tag[k]!=html[0][i+2+k]) 247 break; 248 if(k==len) 249 break; 250 } 251 while(html[0][ii]!='>') 252 putchar(html[0][ii++]); 253 putchar(html[0][ii++]); 254 cout<<stored[j]; 255 while(html[0][i]!='>') 256 putchar(html[0][i++]); 257 putchar(html[0][i++]); 258 } 259 } 260 } 261 int main() 262 { 263 int T; 264 scanf("%d",&T); 265 for(int cases=1;cases<=T;cases++) 266 { 267 int i,j,n,m; 268 getHtmlFormat(0); 269 scanf("%d",&n); 270 for(i=1; i<=n; i++) 271 { 272 getHtmlFormat(i); 273 scanf("%d",&mapNum[i]); 274 for(j=0; j<mapNum[i]; j++) 275 getMapping(i,j); 276 } 277 getHtmlFormat(n+1);// 待处理的html文件 278 printf("Case #%d:\n",cases); 279 for(i=1; i<=n; i++) 280 if(isStructure(i,n+1)) 281 { 282 output(i); 283 break; 284 } 285 if(i==n+1) 286 printf("Can't Identify"); 287 putchar('\n'); 288 } 289 return 0; 290 }